@pagenflow/email 1.3.6 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Button.d.ts +15 -2
- package/dist/components/Divider.d.ts +1 -0
- package/dist/components/Font.d.ts +30 -0
- package/dist/components/Head.d.ts +16 -1
- package/dist/components/HeadDev.d.ts +9 -1
- package/dist/components/Heading.d.ts +6 -0
- package/dist/components/Icon.d.ts +3 -0
- package/dist/components/Image.d.ts +21 -9
- package/dist/components/MsoConditional.d.ts +29 -0
- package/dist/components/Row.d.ts +4 -1
- package/dist/components/Spacer.d.ts +1 -0
- package/dist/components/Text.d.ts +4 -0
- package/dist/index.cjs.js +755 -314
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +14 -11
- package/dist/index.esm.js +753 -315
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -1531,80 +1531,267 @@ 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$2(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",
|
|
1537
|
-
//
|
|
1538
|
-
const
|
|
1539
|
-
|
|
1540
|
-
|
|
1605
|
+
color = "#ffffff", padding = "12px 24px", borderRadius = "3px", border, width, maxWidth, justifyContent = "center", textAlign = "center", fontSize = "16px", fontWeight = "500", fontStyle, fontFamily = "Arial, sans-serif", lineHeight = "1.2", letterSpacing, textTransform, textDecoration = "none", direction, verticalAlign, opacity, whiteSpace = "normal", wordBreak = "break-word", } = config;
|
|
1606
|
+
// Sanitize fontFamily early so safeFontFamily is available for all paths below.
|
|
1607
|
+
const safeFontFamily = fontFamily
|
|
1608
|
+
? fontFamily.replace(/['"]/g, "")
|
|
1609
|
+
: fontFamily;
|
|
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
|
-
//
|
|
1544
|
-
|
|
1545
|
-
const
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
const
|
|
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$2(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
|
-
//
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
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
|
+
const vmlDirection = direction ? `direction:${direction};` : "";
|
|
1669
|
+
const vmlOpacity = opacity !== undefined ? `opacity:${opacity};` : "";
|
|
1670
|
+
// VML code uses MSO conditional comments to render only in Outlook
|
|
1671
|
+
// Use table with explicit MSO height for vertical centering
|
|
1672
|
+
const horizontalPaddingValue = padding.split(" ")[1]
|
|
1673
|
+
? parseInt(padding.split(" ")[1], 10)
|
|
1674
|
+
: numericPadding;
|
|
1675
|
+
// For VML, we need to use a table inside to properly apply padding and centering
|
|
1676
|
+
let vmlAlignAttr = "";
|
|
1677
|
+
let vmlAlignStyle = "";
|
|
1678
|
+
if (textAlign === "center") {
|
|
1679
|
+
vmlAlignAttr = 'align="center"';
|
|
1680
|
+
}
|
|
1681
|
+
else {
|
|
1682
|
+
vmlAlignStyle = `text-align:${textAlign};`;
|
|
1683
|
+
}
|
|
1684
|
+
vmlButton = `
|
|
1568
1685
|
<!--[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;
|
|
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}">
|
|
1570
1687
|
<w:anchorlock/>
|
|
1571
|
-
<
|
|
1572
|
-
|
|
1573
|
-
|
|
1688
|
+
<v:textbox inset="${horizontalPaddingValue}px,${numericPadding}px,${horizontalPaddingValue}px,${numericPadding}px">
|
|
1689
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse:collapse;">
|
|
1690
|
+
<tr>
|
|
1691
|
+
<td ${vmlAlignAttr} valign="middle" style="${vmlAlignStyle}color:${color};font-family:${safeFontFamily};font-size:${fontSize};font-weight:${vmlFontWeight};${vmlFontStyle}${vmlLetterSpacing}${vmlTextTransform}${vmlTextDecoration}${vmlWhiteSpace}${vmlDirection}${vmlOpacity}line-height:${lineHeight};mso-line-height-rule:exactly;">
|
|
1692
|
+
${typeof children === "string" ? children : ""}
|
|
1693
|
+
</td>
|
|
1694
|
+
</tr>
|
|
1695
|
+
</table>
|
|
1696
|
+
</v:textbox>
|
|
1574
1697
|
</v:roundrect>
|
|
1575
1698
|
<![endif]-->
|
|
1576
1699
|
`;
|
|
1700
|
+
}
|
|
1701
|
+
// --- Simple Outlook Approach for Percentage Widths ---
|
|
1702
|
+
let simpleOutlookButton = "";
|
|
1703
|
+
if (useSimpleOutlookApproach) {
|
|
1704
|
+
// Build consistent inline styles for text properties
|
|
1705
|
+
const textDecorationStyle = textDecoration && textDecoration !== "none"
|
|
1706
|
+
? `text-decoration: ${textDecoration};`
|
|
1707
|
+
: "";
|
|
1708
|
+
const fontStyleProp = fontStyle ? `font-style: ${fontStyle};` : "";
|
|
1709
|
+
const letterSpacingProp = letterSpacing
|
|
1710
|
+
? `letter-spacing: ${letterSpacing};`
|
|
1711
|
+
: "";
|
|
1712
|
+
const textTransformProp = textTransform
|
|
1713
|
+
? `text-transform: ${textTransform};`
|
|
1714
|
+
: "";
|
|
1715
|
+
const whiteSpaceProp = whiteSpace !== "normal" ? `white-space: ${whiteSpace};` : "";
|
|
1716
|
+
const directionProp = direction ? `direction: ${direction};` : "";
|
|
1717
|
+
const opacityProp = opacity !== undefined ? `opacity: ${opacity};` : "";
|
|
1718
|
+
const wordBreakProp = wordBreak !== "break-word" ? `word-break: ${wordBreak};` : "";
|
|
1719
|
+
simpleOutlookButton = `
|
|
1720
|
+
<!--[if mso]>
|
|
1721
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;">
|
|
1722
|
+
<tr>
|
|
1723
|
+
<td align="${align}" style="padding: 0;">
|
|
1724
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="${width || "auto"}" style="border-collapse: collapse;">
|
|
1725
|
+
<tr>
|
|
1726
|
+
<td bgcolor="${backgroundColor}" align="${textAlign}" style="padding: ${padding}; text-align: ${textAlign}; border-radius: ${borderRadius}; ${borderStyleString}">
|
|
1727
|
+
<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
|
+
${typeof children === "string" ? children : ""}
|
|
1729
|
+
</a>
|
|
1730
|
+
</td>
|
|
1731
|
+
</tr>
|
|
1732
|
+
</table>
|
|
1733
|
+
</td>
|
|
1734
|
+
</tr>
|
|
1735
|
+
</table>
|
|
1736
|
+
<![endif]-->
|
|
1737
|
+
`;
|
|
1738
|
+
}
|
|
1739
|
+
// Build shared inline style fragments for the non-MSO path.
|
|
1740
|
+
// fontFamily uses the sanitized value so embedded quotes never break the
|
|
1741
|
+
// style attribute string (which is always wrapped in double quotes).
|
|
1742
|
+
const sharedTextStyles = [
|
|
1743
|
+
`color: ${color};`,
|
|
1744
|
+
safeFontFamily ? `font-family: ${safeFontFamily};` : "",
|
|
1745
|
+
fontSize ? `font-size: ${fontSize};` : "",
|
|
1746
|
+
fontWeight ? `font-weight: ${fontWeight};` : "",
|
|
1747
|
+
fontStyle ? `font-style: ${fontStyle};` : "",
|
|
1748
|
+
lineHeight ? `line-height: ${lineHeight};` : "",
|
|
1749
|
+
letterSpacing ? `letter-spacing: ${letterSpacing};` : "",
|
|
1750
|
+
textTransform ? `text-transform: ${textTransform};` : "",
|
|
1751
|
+
textDecoration && textDecoration !== "none"
|
|
1752
|
+
? `text-decoration: ${textDecoration};`
|
|
1753
|
+
: "",
|
|
1754
|
+
direction ? `direction: ${direction};` : "",
|
|
1755
|
+
opacity !== undefined ? `opacity: ${opacity};` : "",
|
|
1756
|
+
whiteSpace !== "normal" ? `white-space: ${whiteSpace};` : "",
|
|
1757
|
+
]
|
|
1758
|
+
.filter(Boolean)
|
|
1759
|
+
.join(" ");
|
|
1577
1760
|
return (
|
|
1578
|
-
//
|
|
1579
|
-
jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0,
|
|
1580
|
-
|
|
1581
|
-
position: "relative",
|
|
1582
|
-
// --- End dev
|
|
1583
|
-
width: width || "auto",
|
|
1761
|
+
// Wrapper table for alignment - maintains proper positioning for hover indicators
|
|
1762
|
+
jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1763
|
+
width: "100%",
|
|
1584
1764
|
borderCollapse: "collapse",
|
|
1585
|
-
// base
|
|
1586
1765
|
boxSizing: "border-box",
|
|
1587
1766
|
border: 0,
|
|
1588
1767
|
margin: 0,
|
|
1589
1768
|
padding: 0,
|
|
1590
|
-
},
|
|
1591
|
-
|
|
1592
|
-
|
|
1769
|
+
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: align, style: {
|
|
1770
|
+
padding: 0,
|
|
1771
|
+
}, children: jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign(Object.assign({
|
|
1772
|
+
// --- Start dev
|
|
1773
|
+
position: "relative",
|
|
1774
|
+
// --- End dev
|
|
1775
|
+
width: width || "auto" }, (maxWidth && { maxWidth: maxWidth })), { borderCollapse: "collapse",
|
|
1776
|
+
// 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: {
|
|
1778
|
+
__html: `
|
|
1779
|
+
${devMode ? "" : useSimpleOutlookApproach ? simpleOutlookButton : vmlButton}
|
|
1593
1780
|
<!--[if !mso]><!-->
|
|
1594
1781
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
|
|
1595
1782
|
<tbody>
|
|
1596
1783
|
<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%;">
|
|
1784
|
+
<td style="background-color: ${backgroundTdStyle.backgroundColor}; border-radius: ${backgroundTdStyle.borderRadius}; width: ${backgroundTdStyle.width}; ${maxWidth ? `max-width: ${maxWidth};` : ""} ${borderRadius ? "overflow: hidden;" : ""}">
|
|
1785
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}; width: 100%; ${borderStyleString}">
|
|
1599
1786
|
<tbody>
|
|
1600
1787
|
<tr>
|
|
1601
|
-
<td style="padding:
|
|
1788
|
+
<td style="padding: 0;">
|
|
1602
1789
|
${devMode
|
|
1603
|
-
|
|
1790
|
+
? `<span style="${sharedTextStyles} display: block; text-align: ${textAlign}; word-break: ${wordBreak}; padding: ${padding};">
|
|
1604
1791
|
${typeof children === "string" ? children : ""}
|
|
1605
1792
|
</span>`
|
|
1606
|
-
|
|
1607
|
-
<span style="
|
|
1793
|
+
: `<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}">
|
|
1608
1795
|
${typeof children === "string" ? children : ""}
|
|
1609
1796
|
</span>
|
|
1610
1797
|
</a>`}
|
|
@@ -1618,7 +1805,7 @@ function Button({ config, devMode }) {
|
|
|
1618
1805
|
</table>
|
|
1619
1806
|
<!--<![endif]-->
|
|
1620
1807
|
`,
|
|
1621
|
-
|
|
1808
|
+
} }) }) }) }) }) }) }) }));
|
|
1622
1809
|
}
|
|
1623
1810
|
var Button_default = React.memo(Button, arePropsEqual);
|
|
1624
1811
|
|
|
@@ -1635,15 +1822,27 @@ const alignMap$2 = {
|
|
|
1635
1822
|
end: "right",
|
|
1636
1823
|
};
|
|
1637
1824
|
// Helper to convert border config to CSS border shorthand
|
|
1638
|
-
function getBorderStyle$
|
|
1825
|
+
function getBorderStyle$5(border) {
|
|
1639
1826
|
if (!border)
|
|
1640
1827
|
return {};
|
|
1641
1828
|
const style = {};
|
|
1642
|
-
//
|
|
1829
|
+
// If a full border is specified, apply it
|
|
1643
1830
|
if (border.width && border.style && border.color) {
|
|
1644
1831
|
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
1645
1832
|
}
|
|
1646
|
-
|
|
1833
|
+
else {
|
|
1834
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
1835
|
+
// to prevent Outlook Classic from showing black borders
|
|
1836
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
1837
|
+
if (hasIndividualBorders) {
|
|
1838
|
+
// Default all borders to none
|
|
1839
|
+
style.borderTop = "none";
|
|
1840
|
+
style.borderRight = "none";
|
|
1841
|
+
style.borderBottom = "none";
|
|
1842
|
+
style.borderLeft = "none";
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
// Override with specific borders if provided
|
|
1647
1846
|
if (border.top) {
|
|
1648
1847
|
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
1649
1848
|
}
|
|
@@ -1663,24 +1862,32 @@ function Column({ children, config, devNode }) {
|
|
|
1663
1862
|
// Process children array for gap support
|
|
1664
1863
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
1665
1864
|
const numChildren = childrenArray.length;
|
|
1666
|
-
// 1. Outer table style: Takes up the full width/height of its parent TD
|
|
1865
|
+
// 1. Outer table style: Takes up the full width/height of its parent TD.
|
|
1866
|
+
// height here drives the *total* outer height of the column.
|
|
1667
1867
|
const outerTableStyle = {
|
|
1668
1868
|
width: "100%",
|
|
1669
1869
|
height: config.height,
|
|
1670
1870
|
borderCollapse: "collapse",
|
|
1671
1871
|
};
|
|
1672
|
-
// 2. Outer TD style: Background and Border Radius (no border here)
|
|
1872
|
+
// 2. Outer TD style: Background and Border Radius (no border here).
|
|
1873
|
+
// height is set so the TD occupies the full declared height.
|
|
1673
1874
|
const outerTdStyle = Object.assign({ width: config.width, height: config.height, backgroundColor: config.backgroundColor, borderRadius: config.borderRadius,
|
|
1674
1875
|
// Background Image styles
|
|
1675
1876
|
backgroundImage: config.backgroundImage
|
|
1676
1877
|
? `url(${config.backgroundImage.src})`
|
|
1677
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" }));
|
|
1678
|
-
// 2b. Inner table style: Border and Border Radius
|
|
1679
|
-
|
|
1680
|
-
|
|
1879
|
+
// 2b. Inner table style: Border and Border Radius.
|
|
1880
|
+
// 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
|
+
// 3. Inner TD style: Padding and Vertical Alignment only.
|
|
1883
|
+
// *** No height here. ***
|
|
1884
|
+
// The outer TD/table owns the height; padding is purely inner spacing,
|
|
1885
|
+
// so the total rendered height = declared height (padding is inside).
|
|
1681
1886
|
const innerTdStyle = {
|
|
1682
1887
|
padding: config.padding,
|
|
1683
|
-
height
|
|
1888
|
+
// height intentionally omitted — setting it here would make browsers
|
|
1889
|
+
// treat it as content-box height and add padding on top, causing the
|
|
1890
|
+
// total to exceed the declared height in preview mode.
|
|
1684
1891
|
verticalAlign: config.alignItems ? alignMap$2[config.alignItems] : "top",
|
|
1685
1892
|
};
|
|
1686
1893
|
// 4. Gap spacer style (used between children)
|
|
@@ -1691,7 +1898,7 @@ function Column({ children, config, devNode }) {
|
|
|
1691
1898
|
width: "100%",
|
|
1692
1899
|
};
|
|
1693
1900
|
// 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",
|
|
1901
|
+
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
1902
|
width: "100%",
|
|
1696
1903
|
borderCollapse: "collapse",
|
|
1697
1904
|
}, children: jsxRuntime.jsx("tbody", { children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
|
|
@@ -1702,7 +1909,7 @@ function Column({ children, config, devNode }) {
|
|
|
1702
1909
|
? vAlignMap[config.justifyContent]
|
|
1703
1910
|
: "top", align: config.alignItems
|
|
1704
1911
|
? 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) })
|
|
1912
|
+
: "left", children: child }) }), index < numChildren - 1 && (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) }) }) }) }));
|
|
1706
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 }) }) }))] })));
|
|
1707
1914
|
}
|
|
1708
1915
|
var Column_default = React.memo(Column, arePropsEqual);
|
|
@@ -1717,13 +1924,27 @@ const justifyMap$2 = {
|
|
|
1717
1924
|
center: "center",
|
|
1718
1925
|
end: "right",
|
|
1719
1926
|
};
|
|
1720
|
-
function getBorderStyle$
|
|
1927
|
+
function getBorderStyle$4(border) {
|
|
1721
1928
|
if (!border)
|
|
1722
1929
|
return {};
|
|
1723
1930
|
const style = {};
|
|
1931
|
+
// If a full border is specified, apply it
|
|
1724
1932
|
if (border.width && border.style && border.color) {
|
|
1725
1933
|
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
1726
1934
|
}
|
|
1935
|
+
else {
|
|
1936
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
1937
|
+
// to prevent Outlook Classic from showing black borders
|
|
1938
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
1939
|
+
if (hasIndividualBorders) {
|
|
1940
|
+
// Default all borders to none
|
|
1941
|
+
style.borderTop = "none";
|
|
1942
|
+
style.borderRight = "none";
|
|
1943
|
+
style.borderBottom = "none";
|
|
1944
|
+
style.borderLeft = "none";
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
// Override with specific borders if provided
|
|
1727
1948
|
if (border.top) {
|
|
1728
1949
|
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
1729
1950
|
}
|
|
@@ -1798,7 +2019,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
1798
2019
|
? `url(${config.backgroundImage.src})`
|
|
1799
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" }));
|
|
1800
2021
|
// 2. Border Table Style - Border and border radius
|
|
1801
|
-
const borderTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$
|
|
2022
|
+
const borderTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$4(config.border));
|
|
1802
2023
|
// 3. Padding TD Style
|
|
1803
2024
|
const innerTdStyle = {
|
|
1804
2025
|
padding: config.padding,
|
|
@@ -1834,7 +2055,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
1834
2055
|
fontSize: "0",
|
|
1835
2056
|
lineHeight: "0",
|
|
1836
2057
|
height: config.gap,
|
|
1837
|
-
}, children: "\u00A0" }))] }, `child-${index}`), jsxRuntime.jsx("td", { className: "desktop-gap-column", width: config.gap, style: gapTdStyle, children: "\u00A0" }, `gap-${index}`)] }, `ctn:${index}`));
|
|
2058
|
+
}, children: "\u00A0" }))] }, `child-${index}`), jsxRuntime.jsx("td", { className: isStacking ? "desktop-gap-column" : undefined, width: config.gap, style: gapTdStyle, children: "\u00A0" }, `gap-${index}`)] }, `ctn:${index}`));
|
|
1838
2059
|
}
|
|
1839
2060
|
return (jsxRuntime.jsx("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: child }, `child-${index}`));
|
|
1840
2061
|
});
|
|
@@ -1852,7 +2073,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
1852
2073
|
var Container_default = React.memo(Container, arePropsEqual);
|
|
1853
2074
|
|
|
1854
2075
|
function Divider({ config, devNode }) {
|
|
1855
|
-
const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", } = config;
|
|
2076
|
+
const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", hideOnMobile, } = config;
|
|
1856
2077
|
// 1. Outer TD Style: Applies the vertical spacing (margin)
|
|
1857
2078
|
const outerTdStyle = {
|
|
1858
2079
|
padding: margin,
|
|
@@ -1881,7 +2102,7 @@ function Divider({ config, devNode }) {
|
|
|
1881
2102
|
// --- End dev
|
|
1882
2103
|
width: "100%",
|
|
1883
2104
|
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: {
|
|
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: {
|
|
1885
2106
|
height: height,
|
|
1886
2107
|
fontSize: "0",
|
|
1887
2108
|
lineHeight: "0",
|
|
@@ -1890,24 +2111,58 @@ function Divider({ config, devNode }) {
|
|
|
1890
2111
|
}
|
|
1891
2112
|
var Divider_default = React.memo(Divider, arePropsEqual);
|
|
1892
2113
|
|
|
1893
|
-
|
|
1894
|
-
|
|
2114
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
2115
|
+
function normaliseFallbacks(fallbackFontFamily) {
|
|
2116
|
+
if (!fallbackFontFamily)
|
|
2117
|
+
return [];
|
|
2118
|
+
return Array.isArray(fallbackFontFamily)
|
|
2119
|
+
? fallbackFontFamily
|
|
2120
|
+
: [fallbackFontFamily];
|
|
2121
|
+
}
|
|
2122
|
+
/**
|
|
2123
|
+
* Build the CSS font-stack string from the primary family + fallbacks.
|
|
2124
|
+
* Wraps names that contain spaces in single quotes.
|
|
2125
|
+
*/
|
|
2126
|
+
function buildFontStack(primary, fallbacks) {
|
|
2127
|
+
const quote = (name) => (name.includes(" ") ? `'${name}'` : name);
|
|
2128
|
+
return [primary, ...fallbacks].map(quote).join(", ");
|
|
2129
|
+
}
|
|
2130
|
+
// ── Component ─────────────────────────────────────────────────────────────────
|
|
2131
|
+
function Font({ fontFamily, fallbackFontFamily, webFont, fontWeight = 400, fontStyle = "normal", }) {
|
|
2132
|
+
var _a;
|
|
2133
|
+
const fallbacks = normaliseFallbacks(fallbackFontFamily);
|
|
2134
|
+
const fontFaceCss = webFont
|
|
2135
|
+
? `
|
|
2136
|
+
@font-face {
|
|
2137
|
+
font-family: '${fontFamily}';
|
|
2138
|
+
font-style: ${fontStyle};
|
|
2139
|
+
font-weight: ${fontWeight};
|
|
2140
|
+
font-display: swap;
|
|
2141
|
+
src: url('${webFont.url}') format('${webFont.format}');
|
|
2142
|
+
mso-font-alt: '${(_a = fallbacks[0]) !== null && _a !== void 0 ? _a : "sans-serif"}';
|
|
2143
|
+
}`.trim()
|
|
2144
|
+
: null;
|
|
2145
|
+
const msoComment = fallbacks.length > 0
|
|
2146
|
+
? `<!--[if mso]>\n<style type="text/css">\n .${cssClassName(fontFamily)} {\n font-family: ${buildFontStack(fallbacks[0], fallbacks.slice(1))}, sans-serif !important;\n }\n</style>\n<![endif]-->`
|
|
2147
|
+
: null;
|
|
2148
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [fontFaceCss && (jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: fontFaceCss } })), msoComment && (jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: {
|
|
2149
|
+
__html: `</style>${msoComment}<style type="text/css">`,
|
|
2150
|
+
} }))] }));
|
|
2151
|
+
}
|
|
2152
|
+
// ── Utility: generate a stable CSS class name from a font family name ─────────
|
|
2153
|
+
// Used in the MSO conditional comment to scope the fallback rule.
|
|
2154
|
+
function cssClassName(fontFamily) {
|
|
2155
|
+
return `font-${fontFamily.toLowerCase().replace(/\s+/g, "-")}`;
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
function Head({ children, backgroundColor = "#ffffff", title = "Email Preview", rowGaps = [], fonts = [], }) {
|
|
1895
2159
|
const msoResetStyles = `
|
|
1896
|
-
/* Forces Outlook to render 100% width and prevents line-height issues */
|
|
1897
2160
|
.ExternalClass { width: 100%; line-height: 100%; }
|
|
1898
2161
|
.ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div { line-height: 100%; }
|
|
1899
|
-
|
|
1900
|
-
/* Reset tables for MSO and border issues */
|
|
1901
2162
|
table { mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: collapse; border-spacing: 0; }
|
|
1902
2163
|
td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
|
1903
|
-
|
|
1904
|
-
/* Reset images */
|
|
1905
2164
|
img { border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; }
|
|
1906
|
-
|
|
1907
|
-
/* Fix for Gmail image wrapping and blue links */
|
|
1908
2165
|
#MessageViewBody img { min-width: 100%; }
|
|
1909
|
-
|
|
1910
|
-
/* --- APPLE BLUE LINK FIX --- */
|
|
1911
2166
|
a[x-apple-data-detectors] {
|
|
1912
2167
|
color: inherit !important;
|
|
1913
2168
|
text-decoration: none !important;
|
|
@@ -1916,14 +2171,8 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
1916
2171
|
font-weight: inherit !important;
|
|
1917
2172
|
line-height: inherit !important;
|
|
1918
2173
|
}
|
|
1919
|
-
|
|
1920
|
-
/* 🔒 NEW: Set global background color via CSS for clients that respect it */
|
|
1921
2174
|
body { background-color: ${backgroundColor} !important; }
|
|
1922
|
-
|
|
1923
|
-
/* Disable browser default margin */
|
|
1924
|
-
p {
|
|
1925
|
-
margin: 0;
|
|
1926
|
-
}
|
|
2175
|
+
p { margin: 0; }
|
|
1927
2176
|
`;
|
|
1928
2177
|
const globalStyles = `
|
|
1929
2178
|
@media screen and (max-width: 768px) {
|
|
@@ -1932,7 +2181,22 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
1932
2181
|
max-width: 100% !important;
|
|
1933
2182
|
}
|
|
1934
2183
|
}
|
|
1935
|
-
|
|
2184
|
+
@media screen and (max-width: 768px) {
|
|
2185
|
+
.hide-on-mobile {
|
|
2186
|
+
display: none !important;
|
|
2187
|
+
max-height: 0 !important;
|
|
2188
|
+
overflow: hidden !important;
|
|
2189
|
+
mso-hide: all;
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
@media screen and (min-width: 769px) {
|
|
2193
|
+
.hide-on-desktop {
|
|
2194
|
+
display: none !important;
|
|
2195
|
+
max-height: 0 !important;
|
|
2196
|
+
overflow: hidden !important;
|
|
2197
|
+
mso-hide: all;
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
1936
2200
|
@media screen and (max-width: 768px) {
|
|
1937
2201
|
.stack-td {
|
|
1938
2202
|
width: 100% !important;
|
|
@@ -1942,12 +2206,7 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
1942
2206
|
padding-left: 0 !important;
|
|
1943
2207
|
padding-right: 0 !important;
|
|
1944
2208
|
}
|
|
1945
|
-
|
|
1946
|
-
.desktop-gap-column {
|
|
1947
|
-
width: 0 !important;
|
|
1948
|
-
display: none !important;
|
|
1949
|
-
}
|
|
1950
|
-
|
|
2209
|
+
.desktop-gap-column { width: 0 !important; display: none !important; }
|
|
1951
2210
|
.mobile-gap-spacer {
|
|
1952
2211
|
display: block !important;
|
|
1953
2212
|
width: 100% !important;
|
|
@@ -1956,143 +2215,38 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
1956
2215
|
mso-line-height-rule: exactly;
|
|
1957
2216
|
}
|
|
1958
2217
|
}
|
|
1959
|
-
|
|
1960
2218
|
@media only screen and (max-width: 768px) {
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
.
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
}
|
|
1967
|
-
.
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
}
|
|
1971
|
-
.responsive-row[data-mobile-justify="end"] .content-table {
|
|
1972
|
-
margin: 0 0 0 auto !important;
|
|
1973
|
-
float: right !important;
|
|
1974
|
-
}
|
|
1975
|
-
|
|
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
|
-
/* 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 {
|
|
2015
|
-
vertical-align: middle !important;
|
|
2016
|
-
}
|
|
2017
|
-
.responsive-row[data-mobile-wrap="true"][data-mobile-align="start"] .child-cell {
|
|
2018
|
-
vertical-align: top !important;
|
|
2019
|
-
}
|
|
2020
|
-
.responsive-row[data-mobile-wrap="true"][data-mobile-align="end"] .child-cell {
|
|
2021
|
-
vertical-align: bottom !important;
|
|
2022
|
-
}
|
|
2023
|
-
|
|
2024
|
-
/* 3. Handling Mobile Wrap - Pure CSS Solution */
|
|
2025
|
-
/* Target only the direct row-content-table, not nested ones */
|
|
2026
|
-
|
|
2027
|
-
/* Force table to act like block container */
|
|
2028
|
-
.responsive-row[data-mobile-wrap="true"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table {
|
|
2029
|
-
width: 100% !important;
|
|
2030
|
-
max-width: 100% !important;
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
/* Force table row to stack cells */
|
|
2034
|
-
.responsive-row[data-mobile-wrap="true"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr {
|
|
2035
|
-
display: block !important;
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
/* Force each child cell to be full width block */
|
|
2039
|
-
.responsive-row[data-mobile-wrap="true"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr > .child-cell {
|
|
2219
|
+
.row-content-table[data-mobile-justify="center"] { margin: 0 auto !important; float: none !important; }
|
|
2220
|
+
.row-content-table[data-mobile-justify="start"] { margin: 0 !important; float: left !important; }
|
|
2221
|
+
.row-content-table[data-mobile-justify="end"] { margin: 0 0 0 auto !important; float: right !important; }
|
|
2222
|
+
.row-content-table[data-mobile-align="center"] .child-cell { vertical-align: middle !important; }
|
|
2223
|
+
.row-content-table[data-mobile-align="start"] .child-cell { vertical-align: top !important; }
|
|
2224
|
+
.row-content-table[data-mobile-align="end"] .child-cell { vertical-align: bottom !important; }
|
|
2225
|
+
.row-content-table[data-mobile-wrap="true"] { width: 100% !important; max-width: 100% !important; }
|
|
2226
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr { display: block !important; }
|
|
2227
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell {
|
|
2040
2228
|
display: block !important;
|
|
2041
2229
|
width: 100% !important;
|
|
2042
2230
|
box-sizing: border-box !important;
|
|
2043
2231
|
}
|
|
2044
|
-
|
|
2045
|
-
/* Hide horizontal gap cells and create vertical spacing with padding */
|
|
2046
|
-
.responsive-row[data-mobile-wrap="true"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr > .row-gap-td {
|
|
2232
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .row-gap-td {
|
|
2047
2233
|
display: none !important;
|
|
2048
2234
|
width: 0 !important;
|
|
2049
2235
|
height: 0 !important;
|
|
2050
2236
|
}
|
|
2051
|
-
|
|
2052
|
-
/* Add vertical spacing between stacked cells using margin */
|
|
2053
|
-
.responsive-row[data-mobile-wrap="true"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2237
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2054
2238
|
margin-bottom: 20px !important;
|
|
2055
2239
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
}
|
|
2064
|
-
.responsive-row[data-mobile-wrap="true"][data-gap="20px"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2065
|
-
margin-bottom: 20px !important;
|
|
2066
|
-
}
|
|
2067
|
-
.responsive-row[data-mobile-wrap="true"][data-gap="24px"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2068
|
-
margin-bottom: 24px !important;
|
|
2069
|
-
}
|
|
2070
|
-
.responsive-row[data-mobile-wrap="true"][data-gap="30px"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2071
|
-
margin-bottom: 30px !important;
|
|
2072
|
-
}
|
|
2073
|
-
.responsive-row[data-mobile-wrap="true"][data-gap="40px"] > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > .row-content-table > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2074
|
-
margin-bottom: 40px !important;
|
|
2075
|
-
}
|
|
2240
|
+
${["10px", "15px", "20px", "24px", "30px", "40px", ...rowGaps]
|
|
2241
|
+
.filter((gap, index, self) => self.indexOf(gap) === index)
|
|
2242
|
+
.map((gap) => `
|
|
2243
|
+
.row-content-table[data-mobile-wrap="true"][data-gap="${gap}"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2244
|
+
margin-bottom: ${gap} !important;
|
|
2245
|
+
}`)
|
|
2246
|
+
.join("\n")}
|
|
2076
2247
|
}
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
/* 🔒 UNIVERSAL LINK RESET */
|
|
2080
|
-
a {
|
|
2081
|
-
color: inherit;
|
|
2082
|
-
text-decoration: none;
|
|
2083
|
-
}
|
|
2084
|
-
/* ================================================= */
|
|
2085
|
-
|
|
2086
|
-
/* ================================================= */
|
|
2087
|
-
/* 🔒 LIST STYLE ENFORCEMENT */
|
|
2088
|
-
|
|
2089
|
-
/* Reset all lists and list items */
|
|
2090
|
-
ol, ul {
|
|
2091
|
-
margin: 0px;
|
|
2092
|
-
padding: 0px;
|
|
2093
|
-
list-style: none;
|
|
2094
|
-
}
|
|
2095
|
-
|
|
2248
|
+
a { color: inherit; text-decoration: none; }
|
|
2249
|
+
ol, ul { margin: 0px; padding: 0px; list-style: none; }
|
|
2096
2250
|
li {
|
|
2097
2251
|
list-style-type: none !important;
|
|
2098
2252
|
list-style: none !important;
|
|
@@ -2101,8 +2255,6 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2101
2255
|
margin: 0px;
|
|
2102
2256
|
display: block !important;
|
|
2103
2257
|
}
|
|
2104
|
-
|
|
2105
|
-
/* 🔒 FORCE HIDE ::marker pseudo-element for non-list items */
|
|
2106
2258
|
li::marker {
|
|
2107
2259
|
content: "" !important;
|
|
2108
2260
|
font-size: 0px !important;
|
|
@@ -2110,24 +2262,18 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2110
2262
|
color: transparent !important;
|
|
2111
2263
|
width: 0px !important;
|
|
2112
2264
|
}
|
|
2113
|
-
|
|
2114
|
-
/* Apply bullet styles only to items with data-list="bullet" */
|
|
2115
2265
|
li[data-list="bullet"] {
|
|
2116
2266
|
list-style-type: disc !important;
|
|
2117
2267
|
list-style-position: inside !important;
|
|
2118
2268
|
padding-left: 1.5em;
|
|
2119
2269
|
display: list-item !important;
|
|
2120
2270
|
}
|
|
2121
|
-
|
|
2122
|
-
/* Apply ordered styles only to items with data-list="ordered" */
|
|
2123
2271
|
li[data-list="ordered"] {
|
|
2124
2272
|
list-style-type: decimal !important;
|
|
2125
2273
|
list-style-position: inside !important;
|
|
2126
2274
|
padding-left: 1.5em;
|
|
2127
2275
|
display: list-item !important;
|
|
2128
2276
|
}
|
|
2129
|
-
|
|
2130
|
-
/* Ensure marker only takes its natural size with no extra spacing */
|
|
2131
2277
|
li[data-list="bullet"]::marker,
|
|
2132
2278
|
li[data-list="ordered"]::marker {
|
|
2133
2279
|
content: normal !important;
|
|
@@ -2137,22 +2283,13 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2137
2283
|
padding: 0 !important;
|
|
2138
2284
|
margin: 0 !important;
|
|
2139
2285
|
}
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
/* ================================================= */
|
|
2143
|
-
/* 🔒 HEADING STYLE RESET */
|
|
2144
|
-
h1, h2, h3, h4, h5, h6 {
|
|
2145
|
-
margin: 0;
|
|
2146
|
-
padding: 0;
|
|
2147
|
-
font-weight: inherit; /* Disables browser defaults */
|
|
2148
|
-
}
|
|
2149
|
-
/* ================================================= */
|
|
2286
|
+
h1, h2, h3, h4, h5, h6 { margin: 0; padding: 0; font-weight: inherit; }
|
|
2150
2287
|
`;
|
|
2151
|
-
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 }), jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: msoResetStyles } }), jsxRuntime.jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: globalStyles } })
|
|
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 } })] }));
|
|
2152
2289
|
}
|
|
2153
2290
|
|
|
2154
2291
|
function Heading({ config, devMode, children }) {
|
|
2155
|
-
const { text, level = "h1", padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, } = config;
|
|
2292
|
+
const { text, level = "h1", padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, wordBreak, whiteSpace, } = config;
|
|
2156
2293
|
// Determine the content to render
|
|
2157
2294
|
const content = text !== null && text !== void 0 ? text : children;
|
|
2158
2295
|
const isString = typeof content === "string";
|
|
@@ -2167,6 +2304,7 @@ function Heading({ config, devMode, children }) {
|
|
|
2167
2304
|
const headingStyle = {
|
|
2168
2305
|
color: color,
|
|
2169
2306
|
textAlign: textAlign,
|
|
2307
|
+
fontFamily: fontFamily || "Arial, Helvetica, sans-serif",
|
|
2170
2308
|
fontSize: fontSize,
|
|
2171
2309
|
fontWeight: fontWeight,
|
|
2172
2310
|
fontStyle: fontStyle,
|
|
@@ -2175,11 +2313,11 @@ function Heading({ config, devMode, children }) {
|
|
|
2175
2313
|
textTransform: textTransform,
|
|
2176
2314
|
textDecoration: textDecoration,
|
|
2177
2315
|
direction: direction,
|
|
2316
|
+
wordBreak: wordBreak,
|
|
2317
|
+
whiteSpace: whiteSpace,
|
|
2178
2318
|
// Critical: Remove default top/bottom margin from HTML heading tags
|
|
2179
2319
|
margin: "0",
|
|
2180
2320
|
padding: "0",
|
|
2181
|
-
// Ensures compatibility with MSO/general font rendering
|
|
2182
|
-
fontFamily: "Arial, Helvetica, sans-serif",
|
|
2183
2321
|
// Outlook specific fixes (using string indexing)
|
|
2184
2322
|
["msoLineHeightRule"]: "exactly",
|
|
2185
2323
|
};
|
|
@@ -2214,61 +2352,196 @@ function Html({ children, backgroundColor = "#ffffff", }) {
|
|
|
2214
2352
|
);
|
|
2215
2353
|
}
|
|
2216
2354
|
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
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
|
+
function getBorderStyle$3(border) {
|
|
2378
|
+
if (!border)
|
|
2379
|
+
return {};
|
|
2380
|
+
const style = {};
|
|
2381
|
+
if (border.width && border.style && border.color) {
|
|
2382
|
+
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2383
|
+
}
|
|
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
|
+
if (border.top)
|
|
2394
|
+
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2395
|
+
if (border.right)
|
|
2396
|
+
style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
|
|
2397
|
+
if (border.bottom)
|
|
2398
|
+
style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
|
|
2399
|
+
if (border.left)
|
|
2400
|
+
style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
|
|
2401
|
+
return style;
|
|
2402
|
+
}
|
|
2403
|
+
function getBorderStyleString$1(border) {
|
|
2404
|
+
if (!border)
|
|
2405
|
+
return "";
|
|
2406
|
+
const styles = [];
|
|
2407
|
+
if (border.width && border.style && border.color) {
|
|
2408
|
+
styles.push(`border:${border.width} ${border.style} ${border.color};`);
|
|
2409
|
+
}
|
|
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
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
if (border.top)
|
|
2417
|
+
styles.push(`border-top:${border.top.width} ${border.top.style} ${border.top.color};`);
|
|
2418
|
+
if (border.right)
|
|
2419
|
+
styles.push(`border-right:${border.right.width} ${border.right.style} ${border.right.color};`);
|
|
2420
|
+
if (border.bottom)
|
|
2421
|
+
styles.push(`border-bottom:${border.bottom.width} ${border.bottom.style} ${border.bottom.color};`);
|
|
2422
|
+
if (border.left)
|
|
2423
|
+
styles.push(`border-left:${border.left.width} ${border.left.style} ${border.left.color};`);
|
|
2424
|
+
return styles.join(" ");
|
|
2425
|
+
}
|
|
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,
|
|
2232
2440
|
};
|
|
2233
|
-
|
|
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);
|
|
2234
2450
|
const linkStyle = {
|
|
2235
2451
|
display: "block",
|
|
2236
2452
|
textDecoration: "none",
|
|
2237
2453
|
border: "0",
|
|
2238
2454
|
outline: "none",
|
|
2239
2455
|
};
|
|
2240
|
-
// 3. TD Style: Where padding and background are reliably applied
|
|
2241
2456
|
const tdStyle = {
|
|
2242
2457
|
padding: padding,
|
|
2243
2458
|
backgroundColor: backgroundColor,
|
|
2244
|
-
fontSize: "0",
|
|
2245
|
-
lineHeight: "0",
|
|
2459
|
+
fontSize: "0",
|
|
2460
|
+
lineHeight: "0",
|
|
2246
2461
|
};
|
|
2247
|
-
|
|
2248
|
-
const
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
if (widthPx && maxWidthPx) {
|
|
2256
|
-
return Math.min(widthPx, maxWidthPx);
|
|
2257
|
-
}
|
|
2258
|
-
return widthPx || maxWidthPx;
|
|
2259
|
-
})(), height: (height === null || height === void 0 ? void 0 : height.endsWith("px")) ? parseInt(height, 10) : undefined, border: 0 }));
|
|
2260
|
-
// Wrap image in link if href is provided and not in dev mode
|
|
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 }));
|
|
2261
2470
|
const content = href && !devMode ? (jsxRuntime.jsx("a", Object.assign({ href: href, target: target, style: linkStyle }, (target === "_blank" ? { rel: "noopener noreferrer" } : {}), { children: imageElement }))) : (imageElement);
|
|
2262
|
-
return (
|
|
2263
|
-
// We wrap the image in a table to reliably apply padding, background, and alignment.
|
|
2264
|
-
jsxRuntime.jsxs("table", { "aria-label": `Image Wrapper for: ${alt}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2265
|
-
// --- Start dev
|
|
2471
|
+
return (jsxRuntime.jsxs("table", { "aria-label": `Image Wrapper for: ${alt}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, className: className, style: {
|
|
2266
2472
|
position: "relative",
|
|
2267
|
-
// --- End dev
|
|
2268
2473
|
width: width || "100%",
|
|
2269
2474
|
borderCollapse: "collapse",
|
|
2270
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 }) }) }))] }));
|
|
2271
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
|
+
}) }) }) }) }))] }));
|
|
2544
|
+
}
|
|
2272
2545
|
var Image_default = React.memo(Image, arePropsEqual);
|
|
2273
2546
|
|
|
2274
2547
|
const justifyMap$1 = {
|
|
@@ -2281,13 +2554,27 @@ const alignMap = {
|
|
|
2281
2554
|
center: "middle",
|
|
2282
2555
|
end: "bottom",
|
|
2283
2556
|
};
|
|
2284
|
-
function getBorderStyle$
|
|
2557
|
+
function getBorderStyle$2(border) {
|
|
2285
2558
|
if (!border)
|
|
2286
2559
|
return {};
|
|
2287
2560
|
const style = {};
|
|
2561
|
+
// If a full border is specified, apply it
|
|
2288
2562
|
if (border.width && border.style && border.color) {
|
|
2289
2563
|
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2290
2564
|
}
|
|
2565
|
+
else {
|
|
2566
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
2567
|
+
// to prevent Outlook Classic from showing black borders
|
|
2568
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2569
|
+
if (hasIndividualBorders) {
|
|
2570
|
+
// Default all borders to none
|
|
2571
|
+
style.borderTop = "none";
|
|
2572
|
+
style.borderRight = "none";
|
|
2573
|
+
style.borderBottom = "none";
|
|
2574
|
+
style.borderLeft = "none";
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
// Override with specific borders if provided
|
|
2291
2578
|
if (border.top) {
|
|
2292
2579
|
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2293
2580
|
}
|
|
@@ -2302,23 +2589,50 @@ function getBorderStyle$1(border) {
|
|
|
2302
2589
|
}
|
|
2303
2590
|
return style;
|
|
2304
2591
|
}
|
|
2305
|
-
function
|
|
2306
|
-
|
|
2592
|
+
function getHrefFromInnerLink(innerLink) {
|
|
2593
|
+
if (!innerLink || innerLink.type === "none")
|
|
2594
|
+
return undefined;
|
|
2595
|
+
switch (innerLink.type) {
|
|
2596
|
+
case "url":
|
|
2597
|
+
return innerLink.url;
|
|
2598
|
+
case "email":
|
|
2599
|
+
return innerLink.email ? `mailto:${innerLink.email}` : undefined;
|
|
2600
|
+
case "phone":
|
|
2601
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : undefined;
|
|
2602
|
+
case "anchor":
|
|
2603
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : undefined;
|
|
2604
|
+
case "page_top":
|
|
2605
|
+
return "#";
|
|
2606
|
+
case "page_bottom":
|
|
2607
|
+
return "#bottom";
|
|
2608
|
+
default:
|
|
2609
|
+
return undefined;
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
function Row({ children, config, devNode, devMode }) {
|
|
2613
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2307
2614
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2308
2615
|
const numChildren = childrenArray.length;
|
|
2309
|
-
|
|
2616
|
+
const href = getHrefFromInnerLink(config.innerLink);
|
|
2617
|
+
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.
|
|
2310
2620
|
const backgroundTdStyle = Object.assign({ backgroundColor: config.backgroundColor, borderRadius: config.borderRadius, width: config.width || "100%", height: config.height,
|
|
2311
2621
|
// Background Image styles
|
|
2312
2622
|
backgroundImage: config.backgroundImage
|
|
2313
2623
|
? `url(${config.backgroundImage.src})`
|
|
2314
|
-
: undefined, backgroundRepeat: (
|
|
2315
|
-
// 2. Inner Table for Border and Border Radius
|
|
2316
|
-
|
|
2317
|
-
|
|
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.
|
|
2318
2632
|
const paddingTdStyle = {
|
|
2319
2633
|
padding: config.padding,
|
|
2320
2634
|
width: "100%",
|
|
2321
|
-
height
|
|
2635
|
+
// height intentionally omitted — padding must be inner, not additive
|
|
2322
2636
|
verticalAlign: "top",
|
|
2323
2637
|
};
|
|
2324
2638
|
// 4. Content Table - horizontal layout
|
|
@@ -2339,32 +2653,56 @@ function Row({ children, config, devNode }) {
|
|
|
2339
2653
|
? justifyMap$1[config.justifyContent]
|
|
2340
2654
|
: "left";
|
|
2341
2655
|
const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
|
|
2342
|
-
|
|
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: {
|
|
2343
2658
|
position: "relative",
|
|
2344
2659
|
width: config.width || "100%",
|
|
2345
2660
|
height: config.height,
|
|
2346
2661
|
borderCollapse: "collapse",
|
|
2347
|
-
} }, (config.height && { height: config.height }), {
|
|
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: {
|
|
2348
2663
|
width: "100%",
|
|
2349
2664
|
height: "100%",
|
|
2350
2665
|
borderCollapse: "collapse",
|
|
2351
|
-
}, 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", 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: {
|
|
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: {
|
|
2352
2667
|
verticalAlign: tdValign,
|
|
2353
2668
|
textAlign: "left",
|
|
2354
2669
|
padding: "0",
|
|
2355
2670
|
margin: "0",
|
|
2356
2671
|
}, className: "child-cell", children: child }), index < numChildren - 1 &&
|
|
2357
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
|
|
2674
|
+
if (href && !devMode) {
|
|
2675
|
+
return (jsxRuntime.jsx("a", Object.assign({ href: href }, (target && { target }), { style: {
|
|
2676
|
+
textDecoration: "none",
|
|
2677
|
+
color: "inherit",
|
|
2678
|
+
display: "block",
|
|
2679
|
+
}, children: content })));
|
|
2680
|
+
}
|
|
2681
|
+
return content;
|
|
2358
2682
|
}
|
|
2359
2683
|
var Row_default = React.memo(Row, arePropsEqual);
|
|
2360
2684
|
|
|
2361
|
-
function getBorderStyle(border) {
|
|
2685
|
+
function getBorderStyle$1(border) {
|
|
2362
2686
|
if (!border)
|
|
2363
2687
|
return {};
|
|
2364
2688
|
const style = {};
|
|
2689
|
+
// If a full border is specified, apply it
|
|
2365
2690
|
if (border.width && border.style && border.color) {
|
|
2366
2691
|
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2367
2692
|
}
|
|
2693
|
+
else {
|
|
2694
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
2695
|
+
// to prevent Outlook Classic from showing black borders
|
|
2696
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2697
|
+
if (hasIndividualBorders) {
|
|
2698
|
+
// Default all borders to none
|
|
2699
|
+
style.borderTop = "none";
|
|
2700
|
+
style.borderRight = "none";
|
|
2701
|
+
style.borderBottom = "none";
|
|
2702
|
+
style.borderLeft = "none";
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
// Override with specific borders if provided
|
|
2368
2706
|
if (border.top) {
|
|
2369
2707
|
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2370
2708
|
}
|
|
@@ -2382,7 +2720,7 @@ function getBorderStyle(border) {
|
|
|
2382
2720
|
const Section = ({ config, children, devNode, }) => {
|
|
2383
2721
|
var _a, _b, _c;
|
|
2384
2722
|
const { sectionType, padding } = config;
|
|
2385
|
-
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
|
|
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
|
|
2386
2724
|
? `url(${config.backgroundImage.src})`
|
|
2387
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: {
|
|
2388
2726
|
padding: padding,
|
|
@@ -2399,7 +2737,7 @@ const Section = ({ config, children, devNode, }) => {
|
|
|
2399
2737
|
var Section_default = React.memo(Section, arePropsEqual);
|
|
2400
2738
|
|
|
2401
2739
|
function Spacer({ config, devNode }) {
|
|
2402
|
-
const { height } = config;
|
|
2740
|
+
const { height, hideOnMobile } = config;
|
|
2403
2741
|
// 1. Spacer Table Style
|
|
2404
2742
|
const spacerTableStyle = {
|
|
2405
2743
|
// Crucial for compatibility: Ensures no background or border interference
|
|
@@ -2407,7 +2745,6 @@ function Spacer({ config, devNode }) {
|
|
|
2407
2745
|
borderCollapse: "collapse",
|
|
2408
2746
|
border: "0",
|
|
2409
2747
|
width: "100%",
|
|
2410
|
-
// ✅ FIX: Use string literal indexing for MSO properties
|
|
2411
2748
|
// Note the CSS standard dash convention: 'mso-table-lspace'
|
|
2412
2749
|
// ["mso-table-lspace" as string]: "0pt",
|
|
2413
2750
|
["msoTableLspace"]: "0pt",
|
|
@@ -2428,14 +2765,14 @@ function Spacer({ config, devNode }) {
|
|
|
2428
2765
|
// Outer table ensures the spacer spans the full width of its container
|
|
2429
2766
|
jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign({
|
|
2430
2767
|
// --- Start dev
|
|
2431
|
-
position: "relative" }, spacerTableStyle) }, { height: spacerHeightAttribute }, { children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle,
|
|
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,
|
|
2432
2769
|
// Explicit height attribute
|
|
2433
2770
|
height: spacerHeightAttribute, children: "\u00A0" }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
|
|
2434
2771
|
}
|
|
2435
2772
|
var Spacer_default = React.memo(Spacer, arePropsEqual);
|
|
2436
2773
|
|
|
2437
2774
|
function Text({ config, devMode, children }) {
|
|
2438
|
-
const { text, padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, } = config;
|
|
2775
|
+
const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", } = config;
|
|
2439
2776
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
2440
2777
|
const tdStyle = {
|
|
2441
2778
|
padding: padding,
|
|
@@ -2447,6 +2784,7 @@ function Text({ config, devMode, children }) {
|
|
|
2447
2784
|
const contentStyle = {
|
|
2448
2785
|
color: color,
|
|
2449
2786
|
textAlign: textAlign,
|
|
2787
|
+
fontFamily: fontFamily || "Arial, Helvetica, sans-serif",
|
|
2450
2788
|
fontSize: fontSize,
|
|
2451
2789
|
fontWeight: fontWeight,
|
|
2452
2790
|
fontStyle: fontStyle,
|
|
@@ -2458,9 +2796,9 @@ function Text({ config, devMode, children }) {
|
|
|
2458
2796
|
verticalAlign: verticalAlign,
|
|
2459
2797
|
opacity: opacity,
|
|
2460
2798
|
whiteSpace: whiteSpace,
|
|
2799
|
+
wordBreak: wordBreak,
|
|
2461
2800
|
margin: "0",
|
|
2462
2801
|
padding: "0",
|
|
2463
|
-
fontFamily: "Arial, Helvetica, sans-serif",
|
|
2464
2802
|
};
|
|
2465
2803
|
// Determine content to render
|
|
2466
2804
|
const content = text !== null && text !== void 0 ? text : children;
|
|
@@ -2478,18 +2816,96 @@ const justifyMap = {
|
|
|
2478
2816
|
center: "center",
|
|
2479
2817
|
end: "right",
|
|
2480
2818
|
};
|
|
2819
|
+
function getBorderStyle(border) {
|
|
2820
|
+
if (!border)
|
|
2821
|
+
return {};
|
|
2822
|
+
const style = {};
|
|
2823
|
+
// If a full border is specified, apply it
|
|
2824
|
+
if (border.width && border.style && border.color) {
|
|
2825
|
+
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2826
|
+
}
|
|
2827
|
+
else {
|
|
2828
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
2829
|
+
// to prevent Outlook Classic from showing black borders
|
|
2830
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2831
|
+
if (hasIndividualBorders) {
|
|
2832
|
+
// Default all borders to none
|
|
2833
|
+
style.borderTop = "none";
|
|
2834
|
+
style.borderRight = "none";
|
|
2835
|
+
style.borderBottom = "none";
|
|
2836
|
+
style.borderLeft = "none";
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
// Override with specific borders if provided
|
|
2840
|
+
if (border.top) {
|
|
2841
|
+
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2842
|
+
}
|
|
2843
|
+
if (border.right) {
|
|
2844
|
+
style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
|
|
2845
|
+
}
|
|
2846
|
+
if (border.bottom) {
|
|
2847
|
+
style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
|
|
2848
|
+
}
|
|
2849
|
+
if (border.left) {
|
|
2850
|
+
style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
|
|
2851
|
+
}
|
|
2852
|
+
return style;
|
|
2853
|
+
}
|
|
2854
|
+
function getBorderStyleString(border) {
|
|
2855
|
+
if (!border)
|
|
2856
|
+
return "";
|
|
2857
|
+
const styles = [];
|
|
2858
|
+
// If a full border is specified, apply it
|
|
2859
|
+
if (border.width && border.style && border.color) {
|
|
2860
|
+
styles.push(`border: ${border.width} ${border.style} ${border.color};`);
|
|
2861
|
+
}
|
|
2862
|
+
else {
|
|
2863
|
+
// If only individual borders are specified
|
|
2864
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2865
|
+
if (hasIndividualBorders) {
|
|
2866
|
+
// Default all borders to none
|
|
2867
|
+
styles.push("border-top: none;");
|
|
2868
|
+
styles.push("border-right: none;");
|
|
2869
|
+
styles.push("border-bottom: none;");
|
|
2870
|
+
styles.push("border-left: none;");
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
// Override with specific borders if provided
|
|
2874
|
+
if (border.top) {
|
|
2875
|
+
styles.push(`border-top: ${border.top.width} ${border.top.style} ${border.top.color};`);
|
|
2876
|
+
}
|
|
2877
|
+
if (border.right) {
|
|
2878
|
+
styles.push(`border-right: ${border.right.width} ${border.right.style} ${border.right.color};`);
|
|
2879
|
+
}
|
|
2880
|
+
if (border.bottom) {
|
|
2881
|
+
styles.push(`border-bottom: ${border.bottom.width} ${border.bottom.style} ${border.bottom.color};`);
|
|
2882
|
+
}
|
|
2883
|
+
if (border.left) {
|
|
2884
|
+
styles.push(`border-left: ${border.left.width} ${border.left.style} ${border.left.color};`);
|
|
2885
|
+
}
|
|
2886
|
+
return styles.join(" ");
|
|
2887
|
+
}
|
|
2481
2888
|
// Helper to build Iconify API URL
|
|
2482
2889
|
function buildIconifyUrl(config) {
|
|
2483
2890
|
const { iconIdentifier, height = 24, color = "000000", rotate = 0, rotateOrientation = "cw", } = config;
|
|
2484
2891
|
if (!iconIdentifier)
|
|
2485
2892
|
return null;
|
|
2893
|
+
// Parse height to extract numeric value
|
|
2894
|
+
const parseHeight = (h) => {
|
|
2895
|
+
if (typeof h === "number")
|
|
2896
|
+
return h;
|
|
2897
|
+
// Extract numeric value from string (e.g., "24px" -> 24)
|
|
2898
|
+
const match = String(h).match(/^(-?\d*\.?\d+)/);
|
|
2899
|
+
return match ? parseFloat(match[1]) : 24;
|
|
2900
|
+
};
|
|
2901
|
+
const numericHeight = parseHeight(height);
|
|
2486
2902
|
// Remove # from color if present
|
|
2487
2903
|
const cleanColor = color.replace("#", "");
|
|
2488
2904
|
// Build URL from template
|
|
2489
2905
|
const template = process.env.ICONIFY_API_IMAGE_URI ||
|
|
2490
2906
|
"https://iconify.pagenflow.com/api/image/{{height}}/{{color}}/{{rotate}}-{{rotate-orientation}}/{{icon-full-name}}.png";
|
|
2491
2907
|
return template
|
|
2492
|
-
.replace("{{height}}", String(
|
|
2908
|
+
.replace("{{height}}", String(numericHeight * 2))
|
|
2493
2909
|
.replace("{{color}}", cleanColor)
|
|
2494
2910
|
.replace("{{rotate}}", String(rotate))
|
|
2495
2911
|
.replace("{{rotate-orientation}}", rotateOrientation)
|
|
@@ -2519,12 +2935,15 @@ function buildLinkHref(innerLink) {
|
|
|
2519
2935
|
function Icon({ config, devNode, devMode, children }) {
|
|
2520
2936
|
const {
|
|
2521
2937
|
// base64Source,
|
|
2522
|
-
width, height, backgroundColor, padding = "0", borderRadius = "0", innerLink, justifyContent = "center", } = config;
|
|
2938
|
+
width, height, backgroundColor, padding = "0", borderRadius = "0", border, innerLink, justifyContent = "center", } = config;
|
|
2523
2939
|
// Determine icon source
|
|
2524
2940
|
const iconSrc = buildIconifyUrl(config);
|
|
2525
2941
|
const href = buildLinkHref(innerLink);
|
|
2526
2942
|
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_self";
|
|
2527
2943
|
const align = justifyMap[justifyContent];
|
|
2944
|
+
// Get border styles
|
|
2945
|
+
const borderStyle = getBorderStyle(border);
|
|
2946
|
+
const borderStyleString = getBorderStyleString(border);
|
|
2528
2947
|
// Convert width/height to string with px if number
|
|
2529
2948
|
const widthStr = typeof width === "number" ? `${width}px` : width;
|
|
2530
2949
|
const heightStr = typeof height === "number" ? `${height}px` : height;
|
|
@@ -2545,6 +2964,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2545
2964
|
border: 0, // No default border
|
|
2546
2965
|
width: widthStr || "auto",
|
|
2547
2966
|
height: heightStr || "auto",
|
|
2967
|
+
objectFit: "contain",
|
|
2548
2968
|
};
|
|
2549
2969
|
// 2. Link Style: No underline or color changes
|
|
2550
2970
|
const linkStyle = {
|
|
@@ -2553,14 +2973,21 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2553
2973
|
border: 0,
|
|
2554
2974
|
outline: "none",
|
|
2555
2975
|
};
|
|
2556
|
-
// 3. TD Style:
|
|
2557
|
-
const
|
|
2558
|
-
padding: padding,
|
|
2976
|
+
// 3. Outer TD Style: Background and border-radius wrapper with border
|
|
2977
|
+
const outerTdStyle = {
|
|
2559
2978
|
backgroundColor: backgroundColor,
|
|
2560
|
-
fontSize: "0", // CRITICAL: Collapses extra space
|
|
2561
|
-
lineHeight: "0", // CRITICAL: Collapses extra space7
|
|
2562
2979
|
borderRadius: borderRadius,
|
|
2563
2980
|
overflow: "hidden",
|
|
2981
|
+
fontSize: "0",
|
|
2982
|
+
lineHeight: "0",
|
|
2983
|
+
};
|
|
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);
|
|
2986
|
+
// 5. Inner TD Style: Padding
|
|
2987
|
+
const innerTdStyle = {
|
|
2988
|
+
padding: padding,
|
|
2989
|
+
fontSize: "0", // CRITICAL: Collapses extra space
|
|
2990
|
+
lineHeight: "0", // CRITICAL: Collapses extra space
|
|
2564
2991
|
};
|
|
2565
2992
|
// --- VML Calculation for Outlook Compatibility ---
|
|
2566
2993
|
const numericPadding = parseInt(padding.split(" ")[0] || "0", 10);
|
|
@@ -2577,15 +3004,19 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2577
3004
|
const arcsize = numericBorderRadius > 0
|
|
2578
3005
|
? Math.min((numericBorderRadius / Math.min(vmlWidth, vmlHeight)) * 100, 100)
|
|
2579
3006
|
: 0;
|
|
3007
|
+
// VML stroke color for border
|
|
3008
|
+
const vmlStrokeColor = (border === null || border === void 0 ? void 0 : border.color) || vmlFillColor;
|
|
3009
|
+
const vmlStrokeWeight = (border === null || border === void 0 ? void 0 : border.width) ? parseInt(border.width, 10) : 0;
|
|
3010
|
+
const hasVmlStroke = vmlStrokeWeight > 0;
|
|
2580
3011
|
// Build VML code for Outlook
|
|
2581
3012
|
const vmlIcon = backgroundColor && numericBorderRadius > 0
|
|
2582
3013
|
? `
|
|
2583
3014
|
<!--[if mso]>
|
|
2584
|
-
<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}">
|
|
3015
|
+
<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}">
|
|
2585
3016
|
<w:anchorlock/>
|
|
2586
3017
|
<v:textbox inset="0,0,0,0" style="text-align: center;">
|
|
2587
3018
|
<center style="padding:${padding};">
|
|
2588
|
-
<img src="${iconSrc || ""}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;" />
|
|
3019
|
+
<img src="${iconSrc || ""}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;object-fit:contain;" />
|
|
2589
3020
|
</center>
|
|
2590
3021
|
</v:textbox>
|
|
2591
3022
|
</v:roundrect>
|
|
@@ -2597,8 +3028,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2597
3028
|
return null;
|
|
2598
3029
|
}
|
|
2599
3030
|
// Icon image element
|
|
2600
|
-
const iconElement = devMode && !!children ? (children) : iconSrc ? (jsxRuntime.jsx("img", { draggable: false, src: iconSrc, alt: ""
|
|
2601
|
-
, style: imgStyle, width: widthNum, height: heightNum, border: 0 })) : (jsxRuntime.jsx(jsxRuntime.Fragment, {}));
|
|
3031
|
+
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, {}));
|
|
2602
3032
|
// Wrap in link if href exists and not in dev mode
|
|
2603
3033
|
const content = href && !devMode ? (jsxRuntime.jsx("a", Object.assign({ href: href, target: target, style: linkStyle }, (target === "_blank" ? { rel: "noopener noreferrer" } : {}), { children: iconElement }))) : (iconElement);
|
|
2604
3034
|
// Build the HTML content with VML support (only when NOT in dev mode)
|
|
@@ -2610,12 +3040,20 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2610
3040
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
|
|
2611
3041
|
<tbody>
|
|
2612
3042
|
<tr>
|
|
2613
|
-
<td style="background-color: ${backgroundColor}; border-radius: ${borderRadius};
|
|
2614
|
-
${
|
|
3043
|
+
<td style="background-color: ${backgroundColor}; border-radius: ${borderRadius}; overflow: hidden; font-size: 0; line-height: 0;">
|
|
3044
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}; width: 100%; ${borderStyleString}">
|
|
3045
|
+
<tbody>
|
|
3046
|
+
<tr>
|
|
3047
|
+
<td style="padding: ${padding}; font-size: 0; line-height: 0;">
|
|
3048
|
+
${href
|
|
2615
3049
|
? `<a href="${href}" target="${target}" style="display:block;text-decoration:none;border:0;outline:none;" ${target === "_blank" ? 'rel="noopener noreferrer"' : ""}>
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
: `<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"};" />`}
|
|
3050
|
+
<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;" />
|
|
3051
|
+
</a>`
|
|
3052
|
+
: `<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;" />`}
|
|
3053
|
+
</td>
|
|
3054
|
+
</tr>
|
|
3055
|
+
</tbody>
|
|
3056
|
+
</table>
|
|
2619
3057
|
</td>
|
|
2620
3058
|
</tr>
|
|
2621
3059
|
</tbody>
|
|
@@ -2627,7 +3065,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2627
3065
|
// --- Start dev
|
|
2628
3066
|
position: "relative",
|
|
2629
3067
|
// --- End dev
|
|
2630
|
-
width:
|
|
3068
|
+
width: "auto",
|
|
2631
3069
|
borderCollapse: "collapse",
|
|
2632
3070
|
// base
|
|
2633
3071
|
boxSizing: "border-box",
|
|
@@ -2636,7 +3074,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2636
3074
|
padding: 0,
|
|
2637
3075
|
}, onClick: devMode ? (e) => e.preventDefault() : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: useVML ? (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
|
|
2638
3076
|
__html: htmlContent !== null && htmlContent !== void 0 ? htmlContent : "",
|
|
2639
|
-
} })) : (jsxRuntime.jsx("td", { style:
|
|
3077
|
+
} })) : (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 }) }) }))] }));
|
|
2640
3078
|
}
|
|
2641
3079
|
var Icon_default = React.memo(Icon, arePropsEqual);
|
|
2642
3080
|
|
|
@@ -2645,11 +3083,14 @@ exports.Button = Button_default;
|
|
|
2645
3083
|
exports.Column = Column_default;
|
|
2646
3084
|
exports.Container = Container_default;
|
|
2647
3085
|
exports.Divider = Divider_default;
|
|
3086
|
+
exports.Font = Font;
|
|
2648
3087
|
exports.Head = Head;
|
|
2649
3088
|
exports.Heading = Heading_default;
|
|
2650
3089
|
exports.Html = Html;
|
|
2651
3090
|
exports.Icon = Icon_default;
|
|
2652
3091
|
exports.Image = Image_default;
|
|
3092
|
+
exports.MsoOnly = MsoOnly;
|
|
3093
|
+
exports.NonMso = NonMso;
|
|
2653
3094
|
exports.Row = Row_default;
|
|
2654
3095
|
exports.Section = Section_default;
|
|
2655
3096
|
exports.Spacer = Spacer_default;
|