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