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