@pagenflow/email 1.3.5 → 1.3.7

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
@@ -1531,80 +1531,235 @@ const justifyMap$3 = {
1531
1531
  center: "center",
1532
1532
  end: "right",
1533
1533
  };
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
+ function getBorderStyleString$1(border) {
1570
+ if (!border)
1571
+ return "";
1572
+ const styles = [];
1573
+ // If a full border is specified, apply it
1574
+ if (border.width && border.style && border.color) {
1575
+ styles.push(`border: ${border.width} ${border.style} ${border.color};`);
1576
+ }
1577
+ else {
1578
+ // If only individual borders are specified
1579
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
1580
+ if (hasIndividualBorders) {
1581
+ // Default all borders to none
1582
+ styles.push("border-top: none;");
1583
+ styles.push("border-right: none;");
1584
+ styles.push("border-bottom: none;");
1585
+ styles.push("border-left: none;");
1586
+ }
1587
+ }
1588
+ // Override with specific borders if provided
1589
+ if (border.top) {
1590
+ styles.push(`border-top: ${border.top.width} ${border.top.style} ${border.top.color};`);
1591
+ }
1592
+ if (border.right) {
1593
+ styles.push(`border-right: ${border.right.width} ${border.right.style} ${border.right.color};`);
1594
+ }
1595
+ if (border.bottom) {
1596
+ styles.push(`border-bottom: ${border.bottom.width} ${border.bottom.style} ${border.bottom.color};`);
1597
+ }
1598
+ if (border.left) {
1599
+ styles.push(`border-left: ${border.left.width} ${border.left.style} ${border.left.color};`);
1600
+ }
1601
+ return styles.join(" ");
1602
+ }
1534
1603
  function Button({ config, devMode }) {
1535
1604
  const { href, children, backgroundColor = "#007bff", // Default blue
1536
- color = "#ffffff", padding = "12px 24px", borderRadius = "3px", width, justifyContent = "center", textAlign = "center", fontSize = "16px", fontWeight = "500", fontStyle, lineHeight = "1.2", letterSpacing, textTransform, textDecoration = "none", fontFamily = "Arial, sans-serif", whiteSpace = "normal", } = config;
1605
+ color = "#ffffff", padding = "12px 24px", borderRadius = "3px", border, width, maxWidth, justifyContent = "center", textAlign = "center", fontSize = "16px", fontWeight = "500", fontStyle, lineHeight = "1.2", letterSpacing, textTransform, textDecoration = "none", fontFamily = "Arial, sans-serif", whiteSpace = "normal", } = config;
1537
1606
  // 1. Link (A) Tag Styles (Fallback for Webmail/Mobile)
1538
1607
  const linkStyle = {
1539
1608
  display: "block",
1540
1609
  wordBreak: "break-word"};
1541
1610
  // 2. Outer TD Style for Background and Border Radius (no border)
1542
- const backgroundTdStyle = Object.assign({ backgroundColor: backgroundColor, borderRadius: borderRadius, width: width || "auto" }, (borderRadius && { overflow: "hidden" }));
1543
- // --- VML Calculation and Code for Outlook Compatibility ---
1544
- // VML needs fixed pixel height. We estimate it based on padding.
1545
- const numericPadding = parseInt(padding.split(" ")[0] || "12", 10);
1546
- const vmlHeight = numericPadding * 2 + 20; // Estimate height based on padding + font size
1547
- const vmlWidth = width ? parseInt(width, 10) : 200; // Default VML width (fixed)
1548
- // VML colors must use the full hex format (e.g., #000000)
1549
- const vmlFillColor = backgroundColor.startsWith("#")
1550
- ? backgroundColor
1551
- : `#${backgroundColor}`;
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);
1614
+ const borderStyleString = getBorderStyleString$1(border);
1615
+ // --- Determine Button Approach Based on Width ---
1616
+ // Check if width is percentage-based or not defined
1617
+ const isPercentageWidth = !width || width.includes("%");
1618
+ const useSimpleOutlookApproach = isPercentageWidth;
1552
1619
  const align = justifyMap$3[justifyContent];
1553
- // Build VML font styles
1554
- const vmlFontWeight = fontWeight || "bold";
1555
- const vmlFontStyle = fontStyle === "italic" ? "font-style:italic;" : "";
1556
- const vmlLetterSpacing = letterSpacing
1557
- ? `letter-spacing:${letterSpacing};`
1558
- : "";
1559
- const vmlTextTransform = textTransform
1560
- ? `text-transform:${textTransform};`
1561
- : "";
1562
- const vmlTextDecoration = textDecoration && textDecoration !== "none"
1563
- ? `text-decoration:${textDecoration};`
1564
- : "";
1565
- const vmlWhiteSpace = whiteSpace && whiteSpace !== "normal" ? `white-space:${whiteSpace};` : "";
1566
- // VML code uses MSO conditional comments to render only in Outlook
1567
- const vmlButton = `
1620
+ // --- VML Calculation and Code for Outlook Compatibility (Fixed Width Only) ---
1621
+ let vmlButton = "";
1622
+ if (!useSimpleOutlookApproach) {
1623
+ // VML needs fixed pixel height. We estimate it based on padding and potential wrapping.
1624
+ const numericPadding = parseInt(padding.split(" ")[0] || "12", 10);
1625
+ const numericFontSize = parseInt(fontSize, 10);
1626
+ const numericLineHeight = lineHeight.includes("px")
1627
+ ? parseInt(lineHeight, 10)
1628
+ : numericFontSize * parseFloat(lineHeight);
1629
+ // Trust user's explicit pixel width - no calculation needed
1630
+ const vmlWidth = parseInt(width, 10);
1631
+ // Calculate VML height - trust user's padding and let text wrap naturally
1632
+ // VML v:textbox will handle text wrapping automatically
1633
+ const textContent = typeof children === "string" ? children : "";
1634
+ // Estimate number of lines based on text length and button width
1635
+ const horizontalPadding = padding.split(" ")[1]
1636
+ ? parseInt(padding.split(" ")[1], 10) * 2
1637
+ : numericPadding * 2;
1638
+ const availableTextWidth = vmlWidth - horizontalPadding;
1639
+ const charWidthMultiplier = fontWeight && parseInt(fontWeight) >= 500 ? 0.7 : 0.6;
1640
+ const avgCharWidth = numericFontSize * charWidthMultiplier;
1641
+ const charsPerLine = Math.max(Math.floor(availableTextWidth / avgCharWidth), 1);
1642
+ const numberOfLines = Math.max(Math.ceil(textContent.length / charsPerLine), 1);
1643
+ // Calculate height: vertical padding + (lines * line height) + extra buffer for VML
1644
+ const textHeight = numberOfLines * numericLineHeight;
1645
+ // Add extra 4px buffer to prevent bottom cropping in VML
1646
+ const vmlHeight = Math.max(numericPadding * 2 + textHeight + 4, 40);
1647
+ // VML colors must use the full hex format (e.g., #000000)
1648
+ const vmlFillColor = backgroundColor.startsWith("#")
1649
+ ? backgroundColor
1650
+ : `#${backgroundColor}`;
1651
+ // VML stroke color for border
1652
+ const vmlStrokeColor = (border === null || border === void 0 ? void 0 : border.color) || vmlFillColor;
1653
+ const vmlStrokeWeight = (border === null || border === void 0 ? void 0 : border.width) ? parseInt(border.width, 10) : 0;
1654
+ const hasVmlStroke = vmlStrokeWeight > 0;
1655
+ // Build VML font styles - consistent with other rendering paths
1656
+ const vmlFontWeight = fontWeight || "500";
1657
+ const vmlFontStyle = fontStyle === "italic" ? "font-style:italic;" : "";
1658
+ const vmlLetterSpacing = letterSpacing
1659
+ ? `letter-spacing:${letterSpacing};`
1660
+ : "";
1661
+ const vmlTextTransform = textTransform
1662
+ ? `text-transform:${textTransform};`
1663
+ : "";
1664
+ const vmlTextDecoration = textDecoration && textDecoration !== "none"
1665
+ ? `text-decoration:${textDecoration};`
1666
+ : "";
1667
+ const vmlWhiteSpace = whiteSpace !== "normal" ? `white-space:${whiteSpace};` : "";
1668
+ // VML code uses MSO conditional comments to render only in Outlook
1669
+ // Use table with explicit MSO height for vertical centering
1670
+ const horizontalPaddingValue = padding.split(" ")[1]
1671
+ ? parseInt(padding.split(" ")[1], 10)
1672
+ : numericPadding;
1673
+ // For VML, we need to use a table inside to properly apply padding and centering
1674
+ let vmlAlignAttr = "";
1675
+ let vmlAlignStyle = "";
1676
+ if (textAlign === "center") {
1677
+ vmlAlignAttr = 'align="center"';
1678
+ }
1679
+ else {
1680
+ vmlAlignStyle = `text-align:${textAlign};`;
1681
+ }
1682
+ vmlButton = `
1568
1683
  <!--[if mso]>
1569
- <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="${href}" style="height:${vmlHeight}px;v-text-anchor:middle;width:${vmlWidth}px;" arcsize="${(parseInt(borderRadius) / vmlHeight) * 100}%" strokecolor="${vmlFillColor}" fillcolor="${vmlFillColor}">
1684
+ <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}">
1570
1685
  <w:anchorlock/>
1571
- <center style="color:${color};font-family:${fontFamily};font-size:${fontSize};font-weight:${vmlFontWeight};${vmlFontStyle}${vmlLetterSpacing}${vmlTextTransform}${vmlTextDecoration}${vmlWhiteSpace}">
1572
- ${typeof children === "string" ? children : ""}
1573
- </center>
1686
+ <v:textbox inset="${horizontalPaddingValue}px,${numericPadding}px,${horizontalPaddingValue}px,${numericPadding}px">
1687
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse:collapse;">
1688
+ <tr>
1689
+ <td ${vmlAlignAttr} valign="middle" style="${vmlAlignStyle}color:${color};font-family:${fontFamily};font-size:${fontSize};font-weight:${vmlFontWeight};${vmlFontStyle}${vmlLetterSpacing}${vmlTextTransform}${vmlTextDecoration}${vmlWhiteSpace}line-height:${lineHeight};mso-line-height-rule:exactly;">
1690
+ ${typeof children === "string" ? children : ""}
1691
+ </td>
1692
+ </tr>
1693
+ </table>
1694
+ </v:textbox>
1574
1695
  </v:roundrect>
1575
1696
  <![endif]-->
1576
1697
  `;
1698
+ }
1699
+ // --- Simple Outlook Approach for Percentage Widths ---
1700
+ let simpleOutlookButton = "";
1701
+ if (useSimpleOutlookApproach) {
1702
+ // Build consistent inline styles for text properties
1703
+ const textDecorationStyle = textDecoration && textDecoration !== "none" ? `text-decoration: ${textDecoration};` : "";
1704
+ const fontStyleProp = fontStyle ? `font-style: ${fontStyle};` : "";
1705
+ const letterSpacingProp = letterSpacing ? `letter-spacing: ${letterSpacing};` : "";
1706
+ const textTransformProp = textTransform ? `text-transform: ${textTransform};` : "";
1707
+ const whiteSpaceProp = whiteSpace !== "normal" ? `white-space: ${whiteSpace};` : "";
1708
+ simpleOutlookButton = `
1709
+ <!--[if mso]>
1710
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;">
1711
+ <tr>
1712
+ <td align="${align}" style="padding: 0;">
1713
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="${width || "auto"}" style="border-collapse: collapse;">
1714
+ <tr>
1715
+ <td bgcolor="${backgroundColor}" align="${textAlign}" style="padding: ${padding}; text-align: ${textAlign}; border-radius: ${borderRadius}; ${borderStyleString}">
1716
+ <a href="${href}" target="_blank" rel="noopener noreferrer" style="color: ${color}; ${textDecorationStyle} display: block; font-family: ${fontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; ${fontStyleProp} line-height: ${lineHeight}; ${letterSpacingProp} ${textTransformProp} text-align: ${textAlign}; ${whiteSpaceProp} mso-line-height-rule: exactly;">
1717
+ ${typeof children === "string" ? children : ""}
1718
+ </a>
1719
+ </td>
1720
+ </tr>
1721
+ </table>
1722
+ </td>
1723
+ </tr>
1724
+ </table>
1725
+ <![endif]-->
1726
+ `;
1727
+ }
1577
1728
  return (
1578
- // Outer table for alignment (center the button horizontally)
1579
- jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, style: {
1580
- // --- Start dev
1581
- position: "relative",
1582
- // --- End dev
1583
- width: width || "auto",
1729
+ // Wrapper table for alignment - maintains proper positioning for hover indicators
1730
+ jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
1731
+ width: "100%",
1584
1732
  borderCollapse: "collapse",
1585
- // base
1586
1733
  boxSizing: "border-box",
1587
1734
  border: 0,
1588
1735
  margin: 0,
1589
1736
  padding: 0,
1590
- }, onClick: devMode ? (e) => e.preventDefault() : undefined, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
1591
- __html: `
1592
- ${devMode ? "" : vmlButton}
1737
+ }, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: align, style: {
1738
+ padding: 0,
1739
+ }, children: jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign(Object.assign({
1740
+ // --- Start dev
1741
+ position: "relative",
1742
+ // --- End dev
1743
+ width: width || "auto" }, (maxWidth && { maxWidth: maxWidth })), { borderCollapse: "collapse",
1744
+ // base
1745
+ 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: {
1746
+ __html: `
1747
+ ${devMode ? "" : useSimpleOutlookApproach ? simpleOutlookButton : vmlButton}
1593
1748
  <!--[if !mso]><!-->
1594
1749
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
1595
1750
  <tbody>
1596
1751
  <tr>
1597
- <td style="background-color: ${backgroundTdStyle.backgroundColor}; border-radius: ${backgroundTdStyle.borderRadius}; width: ${backgroundTdStyle.width}; ${borderRadius ? "overflow: hidden;" : ""}">
1598
- <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}; width: 100%;">
1752
+ <td style="background-color: ${backgroundTdStyle.backgroundColor}; border-radius: ${backgroundTdStyle.borderRadius}; width: ${backgroundTdStyle.width}; ${maxWidth ? `max-width: ${maxWidth};` : ""} ${borderRadius ? "overflow: hidden;" : ""}">
1753
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}; width: 100%; ${borderStyleString}">
1599
1754
  <tbody>
1600
1755
  <tr>
1601
- <td style="padding: ${padding};">
1756
+ <td style="padding: 0;">
1602
1757
  ${devMode
1603
- ? `<span style="color: ${color}; font-family: ${fontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; font-style: ${fontStyle || "normal"}; line-height: ${lineHeight}; letter-spacing: ${letterSpacing || "normal"}; text-transform: ${textTransform || "none"}; text-decoration: ${textDecoration}; white-space: ${whiteSpace}; display: ${linkStyle.display}; text-align: ${textAlign}; word-break: ${linkStyle.wordBreak};">
1758
+ ? `<span style="color: ${color}; font-family: ${fontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; ${fontStyle ? `font-style: ${fontStyle};` : ""} line-height: ${lineHeight}; ${letterSpacing ? `letter-spacing: ${letterSpacing};` : ""} ${textTransform ? `text-transform: ${textTransform};` : ""} ${textDecoration && textDecoration !== "none" ? `text-decoration: ${textDecoration};` : ""} ${whiteSpace !== "normal" ? `white-space: ${whiteSpace};` : ""} display: ${linkStyle.display}; text-align: ${textAlign}; word-break: ${linkStyle.wordBreak}; padding: ${padding};">
1604
1759
  ${typeof children === "string" ? children : ""}
1605
1760
  </span>`
1606
- : `<a href="${href}" target="_blank" rel="noopener noreferrer" style="color: ${color}; text-decoration: ${textDecoration}; display: ${linkStyle.display}; word-break: ${linkStyle.wordBreak}; font-family: ${fontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; font-style: ${fontStyle || "normal"}; line-height: ${lineHeight}; letter-spacing: ${letterSpacing || "normal"}; text-transform: ${textTransform || "none"}; text-align: ${textAlign}; white-space: ${whiteSpace};">
1607
- <span style="color: ${color}; font-family: ${fontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; font-style: ${fontStyle || "normal"}; line-height: ${lineHeight}; letter-spacing: ${letterSpacing || "normal"}; text-transform: ${textTransform || "none"}; text-decoration: ${textDecoration}; white-space: ${whiteSpace};">
1761
+ : `<a href="${href}" target="_blank" rel="noopener noreferrer" style="color: ${color}; ${textDecoration && textDecoration !== "none" ? `text-decoration: ${textDecoration};` : "text-decoration: none;"} display: ${linkStyle.display}; word-break: ${linkStyle.wordBreak}; font-family: ${fontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; ${fontStyle ? `font-style: ${fontStyle};` : ""} line-height: ${lineHeight}; ${letterSpacing ? `letter-spacing: ${letterSpacing};` : ""} ${textTransform ? `text-transform: ${textTransform};` : ""} text-align: ${textAlign}; ${whiteSpace !== "normal" ? `white-space: ${whiteSpace};` : ""} padding: ${padding};">
1762
+ <span style="color: ${color}; font-family: ${fontFamily}; font-size: ${fontSize}; font-weight: ${fontWeight}; ${fontStyle ? `font-style: ${fontStyle};` : ""} line-height: ${lineHeight}; ${letterSpacing ? `letter-spacing: ${letterSpacing};` : ""} ${textTransform ? `text-transform: ${textTransform};` : ""} ${textDecoration && textDecoration !== "none" ? `text-decoration: ${textDecoration};` : ""} ${whiteSpace !== "normal" ? `white-space: ${whiteSpace};` : ""}">
1608
1763
  ${typeof children === "string" ? children : ""}
1609
1764
  </span>
1610
1765
  </a>`}
@@ -1618,7 +1773,7 @@ function Button({ config, devMode }) {
1618
1773
  </table>
1619
1774
  <!--<![endif]-->
1620
1775
  `,
1621
- } }) }) }) }));
1776
+ } }) }) }) }) }) }) }) }));
1622
1777
  }
1623
1778
  var Button_default = React.memo(Button, arePropsEqual);
1624
1779
 
@@ -1635,15 +1790,27 @@ const alignMap$2 = {
1635
1790
  end: "right",
1636
1791
  };
1637
1792
  // Helper to convert border config to CSS border shorthand
1638
- function getBorderStyle$3(border) {
1793
+ function getBorderStyle$5(border) {
1639
1794
  if (!border)
1640
1795
  return {};
1641
1796
  const style = {};
1642
- // Check for unified border
1797
+ // If a full border is specified, apply it
1643
1798
  if (border.width && border.style && border.color) {
1644
1799
  style.border = `${border.width} ${border.style} ${border.color}`;
1645
1800
  }
1646
- // Individual sides override unified border
1801
+ else {
1802
+ // If only individual borders are specified, explicitly set others to 'none'
1803
+ // to prevent Outlook Classic from showing black borders
1804
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
1805
+ if (hasIndividualBorders) {
1806
+ // Default all borders to none
1807
+ style.borderTop = "none";
1808
+ style.borderRight = "none";
1809
+ style.borderBottom = "none";
1810
+ style.borderLeft = "none";
1811
+ }
1812
+ }
1813
+ // Override with specific borders if provided
1647
1814
  if (border.top) {
1648
1815
  style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
1649
1816
  }
@@ -1663,24 +1830,32 @@ function Column({ children, config, devNode }) {
1663
1830
  // Process children array for gap support
1664
1831
  const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
1665
1832
  const numChildren = childrenArray.length;
1666
- // 1. Outer table style: Takes up the full width/height of its parent TD
1833
+ // 1. Outer table style: Takes up the full width/height of its parent TD.
1834
+ // height here drives the *total* outer height of the column.
1667
1835
  const outerTableStyle = {
1668
1836
  width: "100%",
1669
1837
  height: config.height,
1670
1838
  borderCollapse: "collapse",
1671
1839
  };
1672
- // 2. Outer TD style: Background and Border Radius (no border here)
1840
+ // 2. Outer TD style: Background and Border Radius (no border here).
1841
+ // height is set so the TD occupies the full declared height.
1673
1842
  const outerTdStyle = Object.assign({ width: config.width, height: config.height, backgroundColor: config.backgroundColor, borderRadius: config.borderRadius,
1674
1843
  // Background Image styles
1675
1844
  backgroundImage: config.backgroundImage
1676
1845
  ? `url(${config.backgroundImage.src})`
1677
1846
  : 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" }));
1678
- // 2b. Inner table style: Border and Border Radius
1679
- const innerTableStyle = Object.assign({ width: "100%", height: config.height, borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$3(config.border));
1680
- // 3. Inner TD style: Padding and Vertical Alignment
1847
+ // 2b. Inner table style: Border and Border Radius.
1848
+ // height: 100% so it stretches to fill the outer TD's declared height.
1849
+ const innerTableStyle = Object.assign({ width: "100%", height: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$5(config.border));
1850
+ // 3. Inner TD style: Padding and Vertical Alignment only.
1851
+ // *** No height here. ***
1852
+ // The outer TD/table owns the height; padding is purely inner spacing,
1853
+ // so the total rendered height = declared height (padding is inside).
1681
1854
  const innerTdStyle = {
1682
1855
  padding: config.padding,
1683
- height: config.height,
1856
+ // height intentionally omitted — setting it here would make browsers
1857
+ // treat it as content-box height and add padding on top, causing the
1858
+ // total to exceed the declared height in preview mode.
1684
1859
  verticalAlign: config.alignItems ? alignMap$2[config.alignItems] : "top",
1685
1860
  };
1686
1861
  // 4. Gap spacer style (used between children)
@@ -1691,7 +1866,7 @@ function Column({ children, config, devNode }) {
1691
1866
  width: "100%",
1692
1867
  };
1693
1868
  // Main content rendering
1694
- const renderContent = () => (jsxRuntime.jsx("table", { "aria-label": "Column Padding", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", Object.assign({ style: innerTdStyle, valign: config.justifyContent ? vAlignMap[config.justifyContent] : "top", align: config.alignItems ? alignMap$2[config.alignItems] : "left" }, (config.height && { height: config.height }), { children: config.gap && numChildren > 1 ? (jsxRuntime.jsx("table", { "aria-label": "Column Gap Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
1869
+ const renderContent = () => (jsxRuntime.jsx("table", { "aria-label": "Column Padding", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: innerTdStyle, valign: config.justifyContent ? vAlignMap[config.justifyContent] : "top", align: config.alignItems ? alignMap$2[config.alignItems] : "left", children: config.gap && numChildren > 1 ? (jsxRuntime.jsx("table", { "aria-label": "Column Gap Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
1695
1870
  width: "100%",
1696
1871
  borderCollapse: "collapse",
1697
1872
  }, children: jsxRuntime.jsx("tbody", { children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
@@ -1702,7 +1877,7 @@ function Column({ children, config, devNode }) {
1702
1877
  ? vAlignMap[config.justifyContent]
1703
1878
  : "top", align: config.alignItems
1704
1879
  ? alignMap$2[config.alignItems]
1705
- : "left", children: child }) }), index < numChildren - 1 && (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) })) }) }) }));
1880
+ : "left", children: child }) }), index < numChildren - 1 && (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) }) }) }) }));
1706
1881
  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 }) }) }))] })));
1707
1882
  }
1708
1883
  var Column_default = React.memo(Column, arePropsEqual);
@@ -1717,13 +1892,27 @@ const justifyMap$2 = {
1717
1892
  center: "center",
1718
1893
  end: "right",
1719
1894
  };
1720
- function getBorderStyle$2(border) {
1895
+ function getBorderStyle$4(border) {
1721
1896
  if (!border)
1722
1897
  return {};
1723
1898
  const style = {};
1899
+ // If a full border is specified, apply it
1724
1900
  if (border.width && border.style && border.color) {
1725
1901
  style.border = `${border.width} ${border.style} ${border.color}`;
1726
1902
  }
1903
+ else {
1904
+ // If only individual borders are specified, explicitly set others to 'none'
1905
+ // to prevent Outlook Classic from showing black borders
1906
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
1907
+ if (hasIndividualBorders) {
1908
+ // Default all borders to none
1909
+ style.borderTop = "none";
1910
+ style.borderRight = "none";
1911
+ style.borderBottom = "none";
1912
+ style.borderLeft = "none";
1913
+ }
1914
+ }
1915
+ // Override with specific borders if provided
1727
1916
  if (border.top) {
1728
1917
  style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
1729
1918
  }
@@ -1798,7 +1987,7 @@ function Container({ children, config, devMode, devNode }) {
1798
1987
  ? `url(${config.backgroundImage.src})`
1799
1988
  : 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" }));
1800
1989
  // 2. Border Table Style - Border and border radius
1801
- const borderTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$2(config.border));
1990
+ const borderTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$4(config.border));
1802
1991
  // 3. Padding TD Style
1803
1992
  const innerTdStyle = {
1804
1993
  padding: config.padding,
@@ -1852,7 +2041,7 @@ function Container({ children, config, devMode, devNode }) {
1852
2041
  var Container_default = React.memo(Container, arePropsEqual);
1853
2042
 
1854
2043
  function Divider({ config, devNode }) {
1855
- const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", } = config;
2044
+ const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", hideOnMobile, } = config;
1856
2045
  // 1. Outer TD Style: Applies the vertical spacing (margin)
1857
2046
  const outerTdStyle = {
1858
2047
  padding: margin,
@@ -1881,7 +2070,7 @@ function Divider({ config, devNode }) {
1881
2070
  // --- End dev
1882
2071
  width: "100%",
1883
2072
  borderCollapse: "collapse",
1884
- }, 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: {
2073
+ }, 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: {
1885
2074
  height: height,
1886
2075
  fontSize: "0",
1887
2076
  lineHeight: "0",
@@ -1890,7 +2079,7 @@ function Divider({ config, devNode }) {
1890
2079
  }
1891
2080
  var Divider_default = React.memo(Divider, arePropsEqual);
1892
2081
 
1893
- function Head({ children, backgroundColor = "#ffffff", title = "Email Preview", }) {
2082
+ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview", rowGaps = [], }) {
1894
2083
  // Outlook (MSO) Styles and Reset
1895
2084
  const msoResetStyles = `
1896
2085
  /* Forces Outlook to render 100% width and prevents line-height issues */
@@ -1933,6 +2122,15 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
1933
2122
  }
1934
2123
  }
1935
2124
 
2125
+ @media screen and (max-width: 768px) {
2126
+ .hide-on-mobile {
2127
+ display: none !important;
2128
+ max-height: 0 !important;
2129
+ overflow: hidden !important;
2130
+ mso-hide: all;
2131
+ }
2132
+ }
2133
+
1936
2134
  @media screen and (max-width: 768px) {
1937
2135
  .stack-td {
1938
2136
  width: 100% !important;
@@ -1958,119 +2156,71 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
1958
2156
  }
1959
2157
 
1960
2158
  @media only screen and (max-width: 768px) {
1961
- /* 1. Handling Mobile Alignment (Justify) - Works for both wrapped and non-wrapped */
1962
- /* We target the inner table alignment */
1963
- .responsive-row[data-mobile-justify="center"] .content-table {
2159
+ /* 1. Handling Mobile Alignment (Justify) */
2160
+ .row-content-table[data-mobile-justify="center"] {
1964
2161
  margin: 0 auto !important;
1965
2162
  float: none !important;
1966
2163
  }
1967
- .responsive-row[data-mobile-justify="start"] .content-table {
2164
+ .row-content-table[data-mobile-justify="start"] {
1968
2165
  margin: 0 !important;
1969
2166
  float: left !important;
1970
2167
  }
1971
- .responsive-row[data-mobile-justify="end"] .content-table {
2168
+ .row-content-table[data-mobile-justify="end"] {
1972
2169
  margin: 0 0 0 auto !important;
1973
2170
  float: right !important;
1974
2171
  }
1975
2172
 
1976
- /* Mobile justify for wrapped children - we need to target the outer wrapper td */
1977
- .responsive-row[data-mobile-wrap="true"][data-mobile-justify="center"] td[align] {
1978
- text-align: center !important;
1979
- }
1980
- .responsive-row[data-mobile-wrap="true"][data-mobile-justify="start"] td[align] {
1981
- text-align: left !important;
1982
- }
1983
- .responsive-row[data-mobile-wrap="true"][data-mobile-justify="end"] td[align] {
1984
- text-align: right !important;
1985
- }
1986
-
1987
- /* Also apply to child content tables for better support */
1988
- .responsive-row[data-mobile-wrap="true"][data-mobile-justify="center"] .child-cell table {
1989
- margin-left: auto !important;
1990
- margin-right: auto !important;
1991
- }
1992
- .responsive-row[data-mobile-wrap="true"][data-mobile-justify="start"] .child-cell table {
1993
- margin-left: 0 !important;
1994
- margin-right: auto !important;
1995
- }
1996
- .responsive-row[data-mobile-wrap="true"][data-mobile-justify="end"] .child-cell table {
1997
- margin-left: auto !important;
1998
- margin-right: 0 !important;
1999
- }
2000
-
2001
2173
  /* 2. Handling Mobile Vertical Alignment (Align Items) */
2002
- /* For non-wrapped rows - controls vertical alignment when cells are side-by-side */
2003
- .responsive-row[data-mobile-align="center"]:not([data-mobile-wrap="true"]) .child-cell {
2004
- vertical-align: middle !important;
2005
- }
2006
- .responsive-row[data-mobile-align="start"]:not([data-mobile-wrap="true"]) .child-cell {
2007
- vertical-align: top !important;
2008
- }
2009
- .responsive-row[data-mobile-align="end"]:not([data-mobile-wrap="true"]) .child-cell {
2010
- vertical-align: bottom !important;
2011
- }
2012
-
2013
- /* For wrapped rows - alignItems controls vertical alignment of content within each child cell */
2014
- .responsive-row[data-mobile-wrap="true"][data-mobile-align="center"] .child-cell {
2174
+ .row-content-table[data-mobile-align="center"] .child-cell {
2015
2175
  vertical-align: middle !important;
2016
2176
  }
2017
- .responsive-row[data-mobile-wrap="true"][data-mobile-align="start"] .child-cell {
2177
+ .row-content-table[data-mobile-align="start"] .child-cell {
2018
2178
  vertical-align: top !important;
2019
2179
  }
2020
- .responsive-row[data-mobile-wrap="true"][data-mobile-align="end"] .child-cell {
2180
+ .row-content-table[data-mobile-align="end"] .child-cell {
2021
2181
  vertical-align: bottom !important;
2022
2182
  }
2023
2183
 
2024
2184
  /* 3. Handling Mobile Wrap - Pure CSS Solution */
2025
- /* Force table to act like block container */
2026
- .responsive-row[data-mobile-wrap="true"] .content-table {
2185
+
2186
+ /* Force table to be full width */
2187
+ .row-content-table[data-mobile-wrap="true"] {
2027
2188
  width: 100% !important;
2028
2189
  max-width: 100% !important;
2029
2190
  }
2030
2191
 
2031
2192
  /* Force table row to stack cells */
2032
- .responsive-row[data-mobile-wrap="true"] .content-tr {
2193
+ .row-content-table[data-mobile-wrap="true"] > tbody > .content-tr {
2033
2194
  display: block !important;
2034
2195
  }
2035
2196
 
2036
2197
  /* Force each child cell to be full width block */
2037
- .responsive-row[data-mobile-wrap="true"] .child-cell {
2198
+ .row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell {
2038
2199
  display: block !important;
2039
2200
  width: 100% !important;
2040
2201
  box-sizing: border-box !important;
2041
2202
  }
2042
2203
 
2043
- /* Hide horizontal gap cells and create vertical spacing with padding */
2044
- .responsive-row[data-mobile-wrap="true"] .row-gap-td {
2204
+ /* Hide horizontal gap cells */
2205
+ .row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .row-gap-td {
2045
2206
  display: none !important;
2046
2207
  width: 0 !important;
2047
2208
  height: 0 !important;
2048
2209
  }
2049
2210
 
2050
2211
  /* Add vertical spacing between stacked cells using margin */
2051
- .responsive-row[data-mobile-wrap="true"] .child-cell:not(:last-child) {
2212
+ .row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell:not(:last-child) {
2052
2213
  margin-bottom: 20px !important;
2053
2214
  }
2054
2215
 
2055
2216
  /* Dynamic gap support - common values */
2056
- .responsive-row[data-mobile-wrap="true"][data-gap="10px"] .child-cell:not(:last-child) {
2057
- margin-bottom: 10px !important;
2058
- }
2059
- .responsive-row[data-mobile-wrap="true"][data-gap="15px"] .child-cell:not(:last-child) {
2060
- margin-bottom: 15px !important;
2061
- }
2062
- .responsive-row[data-mobile-wrap="true"][data-gap="20px"] .child-cell:not(:last-child) {
2063
- margin-bottom: 20px !important;
2064
- }
2065
- .responsive-row[data-mobile-wrap="true"][data-gap="24px"] .child-cell:not(:last-child) {
2066
- margin-bottom: 24px !important;
2067
- }
2068
- .responsive-row[data-mobile-wrap="true"][data-gap="30px"] .child-cell:not(:last-child) {
2069
- margin-bottom: 30px !important;
2070
- }
2071
- .responsive-row[data-mobile-wrap="true"][data-gap="40px"] .child-cell:not(:last-child) {
2072
- margin-bottom: 40px !important;
2073
- }
2217
+ ${["10px", "15px", "20px", "24px", "30px", "40px", ...rowGaps]
2218
+ .filter((gap, index, self) => self.indexOf(gap) === index)
2219
+ .map((gap) => `
2220
+ .row-content-table[data-mobile-wrap="true"][data-gap="${gap}"] > tbody > .content-tr > .child-cell:not(:last-child) {
2221
+ margin-bottom: ${gap} !important;
2222
+ }`)
2223
+ .join("\n")}
2074
2224
  }
2075
2225
 
2076
2226
  /* ================================================= */
@@ -2150,7 +2300,7 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
2150
2300
  }
2151
2301
 
2152
2302
  function Heading({ config, devMode, children }) {
2153
- const { text, level = "h1", padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, } = config;
2303
+ const { text, level = "h1", padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, wordBreak, whiteSpace, } = config;
2154
2304
  // Determine the content to render
2155
2305
  const content = text !== null && text !== void 0 ? text : children;
2156
2306
  const isString = typeof content === "string";
@@ -2173,6 +2323,8 @@ function Heading({ config, devMode, children }) {
2173
2323
  textTransform: textTransform,
2174
2324
  textDecoration: textDecoration,
2175
2325
  direction: direction,
2326
+ wordBreak: wordBreak,
2327
+ whiteSpace: whiteSpace,
2176
2328
  // Critical: Remove default top/bottom margin from HTML heading tags
2177
2329
  margin: "0",
2178
2330
  padding: "0",
@@ -2212,22 +2364,53 @@ function Html({ children, backgroundColor = "#ffffff", }) {
2212
2364
  );
2213
2365
  }
2214
2366
 
2367
+ function getBorderStyle$3(border) {
2368
+ if (!border)
2369
+ return {};
2370
+ const style = {};
2371
+ // If a full border is specified, apply it
2372
+ if (border.width && border.style && border.color) {
2373
+ style.border = `${border.width} ${border.style} ${border.color}`;
2374
+ }
2375
+ else {
2376
+ // If only individual borders are specified, explicitly set others to 'none'
2377
+ // to prevent Outlook Classic from showing black borders
2378
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
2379
+ if (hasIndividualBorders) {
2380
+ // Default all borders to none
2381
+ style.borderTop = "none";
2382
+ style.borderRight = "none";
2383
+ style.borderBottom = "none";
2384
+ style.borderLeft = "none";
2385
+ }
2386
+ }
2387
+ // Override with specific borders if provided
2388
+ if (border.top) {
2389
+ style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
2390
+ }
2391
+ if (border.right) {
2392
+ style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
2393
+ }
2394
+ if (border.bottom) {
2395
+ style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
2396
+ }
2397
+ if (border.left) {
2398
+ style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
2399
+ }
2400
+ return style;
2401
+ }
2215
2402
  function Image({ config, devNode, devMode }) {
2216
- const { src, alt, width, height, maxHeight, maxWidth, backgroundColor, padding, borderRadius, href, target, } = config;
2403
+ const { src, alt, width, height, maxHeight, maxWidth, backgroundColor, padding, borderRadius, border, href, target, } = config;
2404
+ // Get border styles
2405
+ const borderStyle = getBorderStyle$3(border);
2217
2406
  // 1. Image Style: Critical for compatibility, especially display: block
2218
- const imgStyle = {
2407
+ const imgStyle = Object.assign({
2219
2408
  // Basic image properties
2220
- display: "block", // Prevents extra vertical space/gaps below the image
2221
- objectFit: "cover", // For controlling how the image fits (modern CSS, may be ignored)
2409
+ display: "block", objectFit: "cover",
2222
2410
  // Dimensions (using CSS fallback)
2223
- width: width || "100%",
2224
- height: height || "auto",
2225
- maxWidth: maxWidth || "100%",
2226
- maxHeight: maxHeight,
2411
+ width: width || "100%", height: height || "auto", maxWidth: maxWidth || "100%", maxHeight: maxHeight,
2227
2412
  // Styling
2228
- border: "0", // Ensures no default browser/client border
2229
- borderRadius: borderRadius,
2230
- };
2413
+ border: "0", borderRadius: borderRadius }, borderStyle);
2231
2414
  // 2. Link Style: Ensure no underline or color changes
2232
2415
  const linkStyle = {
2233
2416
  display: "block",
@@ -2279,13 +2462,27 @@ const alignMap = {
2279
2462
  center: "middle",
2280
2463
  end: "bottom",
2281
2464
  };
2282
- function getBorderStyle$1(border) {
2465
+ function getBorderStyle$2(border) {
2283
2466
  if (!border)
2284
2467
  return {};
2285
2468
  const style = {};
2469
+ // If a full border is specified, apply it
2286
2470
  if (border.width && border.style && border.color) {
2287
2471
  style.border = `${border.width} ${border.style} ${border.color}`;
2288
2472
  }
2473
+ else {
2474
+ // If only individual borders are specified, explicitly set others to 'none'
2475
+ // to prevent Outlook Classic from showing black borders
2476
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
2477
+ if (hasIndividualBorders) {
2478
+ // Default all borders to none
2479
+ style.borderTop = "none";
2480
+ style.borderRight = "none";
2481
+ style.borderBottom = "none";
2482
+ style.borderLeft = "none";
2483
+ }
2484
+ }
2485
+ // Override with specific borders if provided
2289
2486
  if (border.top) {
2290
2487
  style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
2291
2488
  }
@@ -2300,23 +2497,50 @@ function getBorderStyle$1(border) {
2300
2497
  }
2301
2498
  return style;
2302
2499
  }
2303
- function Row({ children, config, devNode }) {
2304
- var _a, _b, _c, _d, _e, _f;
2500
+ function getHrefFromInnerLink(innerLink) {
2501
+ if (!innerLink || innerLink.type === "none")
2502
+ return undefined;
2503
+ switch (innerLink.type) {
2504
+ case "url":
2505
+ return innerLink.url;
2506
+ case "email":
2507
+ return innerLink.email ? `mailto:${innerLink.email}` : undefined;
2508
+ case "phone":
2509
+ return innerLink.phone ? `tel:${innerLink.phone}` : undefined;
2510
+ case "anchor":
2511
+ return innerLink.anchor ? `#${innerLink.anchor}` : undefined;
2512
+ case "page_top":
2513
+ return "#";
2514
+ case "page_bottom":
2515
+ return "#bottom";
2516
+ default:
2517
+ return undefined;
2518
+ }
2519
+ }
2520
+ function Row({ children, config, devNode, devMode }) {
2521
+ var _a, _b, _c, _d, _e, _f, _g;
2305
2522
  const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
2306
2523
  const numChildren = childrenArray.length;
2307
- // 1. Outer TD for Background and Border Radius (no border here)
2524
+ const href = getHrefFromInnerLink(config.innerLink);
2525
+ const target = (_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target;
2526
+ // 1. Outer TD for Background and Border Radius (no border here).
2527
+ // height declared here is the *total* outer height.
2308
2528
  const backgroundTdStyle = Object.assign({ backgroundColor: config.backgroundColor, borderRadius: config.borderRadius, width: config.width || "100%", height: config.height,
2309
2529
  // Background Image styles
2310
2530
  backgroundImage: config.backgroundImage
2311
2531
  ? `url(${config.backgroundImage.src})`
2312
- : 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" }));
2313
- // 2. Inner Table for Border and Border Radius
2314
- const borderTableStyle = Object.assign({ width: "100%", height: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$1(config.border));
2315
- // 3. TD for Padding
2532
+ : 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" }));
2533
+ // 2. Inner Table for Border and Border Radius.
2534
+ // height: 100% so it stretches to fill the outer TD.
2535
+ const borderTableStyle = Object.assign({ width: "100%", height: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$2(config.border));
2536
+ // 3. TD for Padding only — no height.
2537
+ // The outer TD owns the total height; setting height here would cause
2538
+ // browsers/email clients to treat it as content-box height and add
2539
+ // padding on top, making the row taller than the declared height.
2316
2540
  const paddingTdStyle = {
2317
2541
  padding: config.padding,
2318
2542
  width: "100%",
2319
- height: "100%",
2543
+ // height intentionally omitted — padding must be inner, not additive
2320
2544
  verticalAlign: "top",
2321
2545
  };
2322
2546
  // 4. Content Table - horizontal layout
@@ -2337,32 +2561,56 @@ function Row({ children, config, devNode }) {
2337
2561
  ? justifyMap$1[config.justifyContent]
2338
2562
  : "left";
2339
2563
  const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
2340
- return (jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2564
+ // Content to render - wrapped in anchor if innerLink is defined
2565
+ const content = (jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2341
2566
  position: "relative",
2342
2567
  width: config.width || "100%",
2343
2568
  height: config.height,
2344
2569
  borderCollapse: "collapse",
2345
- } }, (config.height && { height: config.height }), { "data-mobile-justify": (_d = config.mobile) === null || _d === void 0 ? void 0 : _d.justifyContent, "data-mobile-align": (_e = config.mobile) === null || _e === void 0 ? void 0 : _e.alignItems, "data-mobile-wrap": ((_f = config.mobile) === null || _f === void 0 ? void 0 : _f.wrap) ? "true" : undefined, "data-gap": config.gap, className: "responsive-row", 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: {
2570
+ } }, (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: {
2346
2571
  width: "100%",
2347
2572
  height: "100%",
2348
2573
  borderCollapse: "collapse",
2349
- }, 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", 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: {
2574
+ }, 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: {
2350
2575
  verticalAlign: tdValign,
2351
2576
  textAlign: "left",
2352
2577
  padding: "0",
2353
2578
  margin: "0",
2354
2579
  }, className: "child-cell", children: child }), index < numChildren - 1 &&
2355
2580
  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 }) }) }))] })));
2581
+ // Wrap in anchor tag if innerLink is defined and NOT in dev mode
2582
+ if (href && !devMode) {
2583
+ return (jsxRuntime.jsx("a", Object.assign({ href: href }, (target && { target }), { style: {
2584
+ textDecoration: "none",
2585
+ color: "inherit",
2586
+ display: "block",
2587
+ }, children: content })));
2588
+ }
2589
+ return content;
2356
2590
  }
2357
2591
  var Row_default = React.memo(Row, arePropsEqual);
2358
2592
 
2359
- function getBorderStyle(border) {
2593
+ function getBorderStyle$1(border) {
2360
2594
  if (!border)
2361
2595
  return {};
2362
2596
  const style = {};
2597
+ // If a full border is specified, apply it
2363
2598
  if (border.width && border.style && border.color) {
2364
2599
  style.border = `${border.width} ${border.style} ${border.color}`;
2365
2600
  }
2601
+ else {
2602
+ // If only individual borders are specified, explicitly set others to 'none'
2603
+ // to prevent Outlook Classic from showing black borders
2604
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
2605
+ if (hasIndividualBorders) {
2606
+ // Default all borders to none
2607
+ style.borderTop = "none";
2608
+ style.borderRight = "none";
2609
+ style.borderBottom = "none";
2610
+ style.borderLeft = "none";
2611
+ }
2612
+ }
2613
+ // Override with specific borders if provided
2366
2614
  if (border.top) {
2367
2615
  style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
2368
2616
  }
@@ -2380,7 +2628,7 @@ function getBorderStyle(border) {
2380
2628
  const Section = ({ config, children, devNode, }) => {
2381
2629
  var _a, _b, _c;
2382
2630
  const { sectionType, padding } = config;
2383
- 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(config.border)), { backgroundImage: config.backgroundImage
2631
+ 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
2384
2632
  ? `url(${config.backgroundImage.src})`
2385
2633
  : 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: {
2386
2634
  padding: padding,
@@ -2397,7 +2645,7 @@ const Section = ({ config, children, devNode, }) => {
2397
2645
  var Section_default = React.memo(Section, arePropsEqual);
2398
2646
 
2399
2647
  function Spacer({ config, devNode }) {
2400
- const { height } = config;
2648
+ const { height, hideOnMobile } = config;
2401
2649
  // 1. Spacer Table Style
2402
2650
  const spacerTableStyle = {
2403
2651
  // Crucial for compatibility: Ensures no background or border interference
@@ -2405,7 +2653,6 @@ function Spacer({ config, devNode }) {
2405
2653
  borderCollapse: "collapse",
2406
2654
  border: "0",
2407
2655
  width: "100%",
2408
- // ✅ FIX: Use string literal indexing for MSO properties
2409
2656
  // Note the CSS standard dash convention: 'mso-table-lspace'
2410
2657
  // ["mso-table-lspace" as string]: "0pt",
2411
2658
  ["msoTableLspace"]: "0pt",
@@ -2426,14 +2673,14 @@ function Spacer({ config, devNode }) {
2426
2673
  // Outer table ensures the spacer spans the full width of its container
2427
2674
  jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign({
2428
2675
  // --- Start dev
2429
- position: "relative" }, spacerTableStyle) }, { height: spacerHeightAttribute }, { children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle,
2676
+ 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,
2430
2677
  // Explicit height attribute
2431
2678
  height: spacerHeightAttribute, children: "\u00A0" }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
2432
2679
  }
2433
2680
  var Spacer_default = React.memo(Spacer, arePropsEqual);
2434
2681
 
2435
2682
  function Text({ config, devMode, children }) {
2436
- const { text, padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, } = config;
2683
+ const { text, padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", } = config;
2437
2684
  // 1. TD Style: Where padding and background are reliably applied.
2438
2685
  const tdStyle = {
2439
2686
  padding: padding,
@@ -2456,6 +2703,7 @@ function Text({ config, devMode, children }) {
2456
2703
  verticalAlign: verticalAlign,
2457
2704
  opacity: opacity,
2458
2705
  whiteSpace: whiteSpace,
2706
+ wordBreak: wordBreak,
2459
2707
  margin: "0",
2460
2708
  padding: "0",
2461
2709
  fontFamily: "Arial, Helvetica, sans-serif",
@@ -2476,18 +2724,96 @@ const justifyMap = {
2476
2724
  center: "center",
2477
2725
  end: "right",
2478
2726
  };
2727
+ function getBorderStyle(border) {
2728
+ if (!border)
2729
+ return {};
2730
+ const style = {};
2731
+ // If a full border is specified, apply it
2732
+ if (border.width && border.style && border.color) {
2733
+ style.border = `${border.width} ${border.style} ${border.color}`;
2734
+ }
2735
+ else {
2736
+ // If only individual borders are specified, explicitly set others to 'none'
2737
+ // to prevent Outlook Classic from showing black borders
2738
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
2739
+ if (hasIndividualBorders) {
2740
+ // Default all borders to none
2741
+ style.borderTop = "none";
2742
+ style.borderRight = "none";
2743
+ style.borderBottom = "none";
2744
+ style.borderLeft = "none";
2745
+ }
2746
+ }
2747
+ // Override with specific borders if provided
2748
+ if (border.top) {
2749
+ style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
2750
+ }
2751
+ if (border.right) {
2752
+ style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
2753
+ }
2754
+ if (border.bottom) {
2755
+ style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
2756
+ }
2757
+ if (border.left) {
2758
+ style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
2759
+ }
2760
+ return style;
2761
+ }
2762
+ function getBorderStyleString(border) {
2763
+ if (!border)
2764
+ return "";
2765
+ const styles = [];
2766
+ // If a full border is specified, apply it
2767
+ if (border.width && border.style && border.color) {
2768
+ styles.push(`border: ${border.width} ${border.style} ${border.color};`);
2769
+ }
2770
+ else {
2771
+ // If only individual borders are specified
2772
+ const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
2773
+ if (hasIndividualBorders) {
2774
+ // Default all borders to none
2775
+ styles.push("border-top: none;");
2776
+ styles.push("border-right: none;");
2777
+ styles.push("border-bottom: none;");
2778
+ styles.push("border-left: none;");
2779
+ }
2780
+ }
2781
+ // Override with specific borders if provided
2782
+ if (border.top) {
2783
+ styles.push(`border-top: ${border.top.width} ${border.top.style} ${border.top.color};`);
2784
+ }
2785
+ if (border.right) {
2786
+ styles.push(`border-right: ${border.right.width} ${border.right.style} ${border.right.color};`);
2787
+ }
2788
+ if (border.bottom) {
2789
+ styles.push(`border-bottom: ${border.bottom.width} ${border.bottom.style} ${border.bottom.color};`);
2790
+ }
2791
+ if (border.left) {
2792
+ styles.push(`border-left: ${border.left.width} ${border.left.style} ${border.left.color};`);
2793
+ }
2794
+ return styles.join(" ");
2795
+ }
2479
2796
  // Helper to build Iconify API URL
2480
2797
  function buildIconifyUrl(config) {
2481
2798
  const { iconIdentifier, height = 24, color = "000000", rotate = 0, rotateOrientation = "cw", } = config;
2482
2799
  if (!iconIdentifier)
2483
2800
  return null;
2801
+ // Parse height to extract numeric value
2802
+ const parseHeight = (h) => {
2803
+ if (typeof h === "number")
2804
+ return h;
2805
+ // Extract numeric value from string (e.g., "24px" -> 24)
2806
+ const match = String(h).match(/^(-?\d*\.?\d+)/);
2807
+ return match ? parseFloat(match[1]) : 24;
2808
+ };
2809
+ const numericHeight = parseHeight(height);
2484
2810
  // Remove # from color if present
2485
2811
  const cleanColor = color.replace("#", "");
2486
2812
  // Build URL from template
2487
2813
  const template = process.env.ICONIFY_API_IMAGE_URI ||
2488
2814
  "https://iconify.pagenflow.com/api/image/{{height}}/{{color}}/{{rotate}}-{{rotate-orientation}}/{{icon-full-name}}.png";
2489
2815
  return template
2490
- .replace("{{height}}", String(Number(height) * Number(2)))
2816
+ .replace("{{height}}", String(numericHeight * 2))
2491
2817
  .replace("{{color}}", cleanColor)
2492
2818
  .replace("{{rotate}}", String(rotate))
2493
2819
  .replace("{{rotate-orientation}}", rotateOrientation)
@@ -2517,12 +2843,15 @@ function buildLinkHref(innerLink) {
2517
2843
  function Icon({ config, devNode, devMode, children }) {
2518
2844
  const {
2519
2845
  // base64Source,
2520
- width, height, backgroundColor, padding = "0", borderRadius = "0", innerLink, justifyContent = "center", } = config;
2846
+ width, height, backgroundColor, padding = "0", borderRadius = "0", border, innerLink, justifyContent = "center", } = config;
2521
2847
  // Determine icon source
2522
2848
  const iconSrc = buildIconifyUrl(config);
2523
2849
  const href = buildLinkHref(innerLink);
2524
2850
  const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_self";
2525
2851
  const align = justifyMap[justifyContent];
2852
+ // Get border styles
2853
+ const borderStyle = getBorderStyle(border);
2854
+ const borderStyleString = getBorderStyleString(border);
2526
2855
  // Convert width/height to string with px if number
2527
2856
  const widthStr = typeof width === "number" ? `${width}px` : width;
2528
2857
  const heightStr = typeof height === "number" ? `${height}px` : height;
@@ -2543,6 +2872,7 @@ function Icon({ config, devNode, devMode, children }) {
2543
2872
  border: 0, // No default border
2544
2873
  width: widthStr || "auto",
2545
2874
  height: heightStr || "auto",
2875
+ objectFit: "contain",
2546
2876
  };
2547
2877
  // 2. Link Style: No underline or color changes
2548
2878
  const linkStyle = {
@@ -2551,14 +2881,21 @@ function Icon({ config, devNode, devMode, children }) {
2551
2881
  border: 0,
2552
2882
  outline: "none",
2553
2883
  };
2554
- // 3. TD Style: Padding and background
2555
- const tdStyle = {
2556
- padding: padding,
2884
+ // 3. Outer TD Style: Background and border-radius wrapper with border
2885
+ const outerTdStyle = {
2557
2886
  backgroundColor: backgroundColor,
2558
- fontSize: "0", // CRITICAL: Collapses extra space
2559
- lineHeight: "0", // CRITICAL: Collapses extra space7
2560
2887
  borderRadius: borderRadius,
2561
2888
  overflow: "hidden",
2889
+ fontSize: "0",
2890
+ lineHeight: "0",
2891
+ };
2892
+ // 4. Inner Table Style: Apply border here with border-collapse: separate
2893
+ const innerTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: borderRadius }, borderStyle);
2894
+ // 5. Inner TD Style: Padding
2895
+ const innerTdStyle = {
2896
+ padding: padding,
2897
+ fontSize: "0", // CRITICAL: Collapses extra space
2898
+ lineHeight: "0", // CRITICAL: Collapses extra space
2562
2899
  };
2563
2900
  // --- VML Calculation for Outlook Compatibility ---
2564
2901
  const numericPadding = parseInt(padding.split(" ")[0] || "0", 10);
@@ -2575,15 +2912,19 @@ function Icon({ config, devNode, devMode, children }) {
2575
2912
  const arcsize = numericBorderRadius > 0
2576
2913
  ? Math.min((numericBorderRadius / Math.min(vmlWidth, vmlHeight)) * 100, 100)
2577
2914
  : 0;
2915
+ // VML stroke color for border
2916
+ const vmlStrokeColor = (border === null || border === void 0 ? void 0 : border.color) || vmlFillColor;
2917
+ const vmlStrokeWeight = (border === null || border === void 0 ? void 0 : border.width) ? parseInt(border.width, 10) : 0;
2918
+ const hasVmlStroke = vmlStrokeWeight > 0;
2578
2919
  // Build VML code for Outlook
2579
2920
  const vmlIcon = backgroundColor && numericBorderRadius > 0
2580
2921
  ? `
2581
2922
  <!--[if mso]>
2582
- <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" ${href && !devMode ? `href="${href}"` : ""} style="height:${vmlHeight}px;width:${vmlWidth}px;v-text-anchor:middle;" arcsize="${arcsize}%" stroke="false" fillcolor="${vmlFillColor}">
2923
+ <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" ${href && !devMode ? `href="${href}"` : ""} style="height:${vmlHeight}px;width:${vmlWidth}px;v-text-anchor:middle;" arcsize="${arcsize}%" ${hasVmlStroke ? `strokecolor="${vmlStrokeColor}" strokeweight="${vmlStrokeWeight}px"` : 'stroke="false"'} fillcolor="${vmlFillColor}">
2583
2924
  <w:anchorlock/>
2584
2925
  <v:textbox inset="0,0,0,0" style="text-align: center;">
2585
2926
  <center style="padding:${padding};">
2586
- <img src="${iconSrc || ""}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;" />
2927
+ <img src="${iconSrc || ""}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;object-fit:contain;" />
2587
2928
  </center>
2588
2929
  </v:textbox>
2589
2930
  </v:roundrect>
@@ -2595,8 +2936,7 @@ function Icon({ config, devNode, devMode, children }) {
2595
2936
  return null;
2596
2937
  }
2597
2938
  // Icon image element
2598
- const iconElement = devMode && !!children ? (children) : iconSrc ? (jsxRuntime.jsx("img", { draggable: false, src: iconSrc, alt: "" // Icons are decorative, empty alt is appropriate
2599
- , style: imgStyle, width: widthNum, height: heightNum, border: 0 })) : (jsxRuntime.jsx(jsxRuntime.Fragment, {}));
2939
+ 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, {}));
2600
2940
  // Wrap in link if href exists and not in dev mode
2601
2941
  const content = href && !devMode ? (jsxRuntime.jsx("a", Object.assign({ href: href, target: target, style: linkStyle }, (target === "_blank" ? { rel: "noopener noreferrer" } : {}), { children: iconElement }))) : (iconElement);
2602
2942
  // Build the HTML content with VML support (only when NOT in dev mode)
@@ -2608,12 +2948,20 @@ function Icon({ config, devNode, devMode, children }) {
2608
2948
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
2609
2949
  <tbody>
2610
2950
  <tr>
2611
- <td style="background-color: ${backgroundColor}; border-radius: ${borderRadius}; padding: ${padding}; font-size: 0; line-height: 0; overflow: hidden;">
2612
- ${href
2951
+ <td style="background-color: ${backgroundColor}; border-radius: ${borderRadius}; overflow: hidden; font-size: 0; line-height: 0;">
2952
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}; width: 100%; ${borderStyleString}">
2953
+ <tbody>
2954
+ <tr>
2955
+ <td style="padding: ${padding}; font-size: 0; line-height: 0;">
2956
+ ${href
2613
2957
  ? `<a href="${href}" target="${target}" style="display:block;text-decoration:none;border:0;outline:none;" ${target === "_blank" ? 'rel="noopener noreferrer"' : ""}>
2614
- <img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};" />
2615
- </a>`
2616
- : `<img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};" />`}
2958
+ <img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};object-fit:contain;" />
2959
+ </a>`
2960
+ : `<img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};object-fit:contain;" />`}
2961
+ </td>
2962
+ </tr>
2963
+ </tbody>
2964
+ </table>
2617
2965
  </td>
2618
2966
  </tr>
2619
2967
  </tbody>
@@ -2625,7 +2973,7 @@ function Icon({ config, devNode, devMode, children }) {
2625
2973
  // --- Start dev
2626
2974
  position: "relative",
2627
2975
  // --- End dev
2628
- width: widthStr || "auto",
2976
+ width: "auto",
2629
2977
  borderCollapse: "collapse",
2630
2978
  // base
2631
2979
  boxSizing: "border-box",
@@ -2634,7 +2982,7 @@ function Icon({ config, devNode, devMode, children }) {
2634
2982
  padding: 0,
2635
2983
  }, onClick: devMode ? (e) => e.preventDefault() : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: useVML ? (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
2636
2984
  __html: htmlContent !== null && htmlContent !== void 0 ? htmlContent : "",
2637
- } })) : (jsxRuntime.jsx("td", { style: tdStyle, align: align, children: content })) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
2985
+ } })) : (jsxRuntime.jsx("td", { style: outerTdStyle, align: align, children: jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: innerTdStyle, align: align, children: content }) }) }) }) })) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
2638
2986
  }
2639
2987
  var Icon_default = React.memo(Icon, arePropsEqual);
2640
2988