@pagenflow/email 1.3.5 → 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +529 -181
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +529 -181
- 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,119 +2156,71 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
1958
2156
|
}
|
|
1959
2157
|
|
|
1960
2158
|
@media only screen and (max-width: 768px) {
|
|
1961
|
-
/* 1. Handling Mobile Alignment (Justify)
|
|
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
|
-
|
|
2026
|
-
|
|
2185
|
+
|
|
2186
|
+
/* Force table to be full width */
|
|
2187
|
+
.row-content-table[data-mobile-wrap="true"] {
|
|
2027
2188
|
width: 100% !important;
|
|
2028
2189
|
max-width: 100% !important;
|
|
2029
2190
|
}
|
|
2030
2191
|
|
|
2031
2192
|
/* Force table row to stack cells */
|
|
2032
|
-
.
|
|
2193
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr {
|
|
2033
2194
|
display: block !important;
|
|
2034
2195
|
}
|
|
2035
2196
|
|
|
2036
2197
|
/* Force each child cell to be full width block */
|
|
2037
|
-
.
|
|
2198
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell {
|
|
2038
2199
|
display: block !important;
|
|
2039
2200
|
width: 100% !important;
|
|
2040
2201
|
box-sizing: border-box !important;
|
|
2041
2202
|
}
|
|
2042
2203
|
|
|
2043
|
-
/* Hide horizontal gap cells
|
|
2044
|
-
.
|
|
2204
|
+
/* Hide horizontal gap cells */
|
|
2205
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .row-gap-td {
|
|
2045
2206
|
display: none !important;
|
|
2046
2207
|
width: 0 !important;
|
|
2047
2208
|
height: 0 !important;
|
|
2048
2209
|
}
|
|
2049
2210
|
|
|
2050
2211
|
/* Add vertical spacing between stacked cells using margin */
|
|
2051
|
-
.
|
|
2212
|
+
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2052
2213
|
margin-bottom: 20px !important;
|
|
2053
2214
|
}
|
|
2054
2215
|
|
|
2055
2216
|
/* Dynamic gap support - common values */
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
margin-bottom: 20px !important;
|
|
2064
|
-
}
|
|
2065
|
-
.responsive-row[data-mobile-wrap="true"][data-gap="24px"] .child-cell:not(:last-child) {
|
|
2066
|
-
margin-bottom: 24px !important;
|
|
2067
|
-
}
|
|
2068
|
-
.responsive-row[data-mobile-wrap="true"][data-gap="30px"] .child-cell:not(:last-child) {
|
|
2069
|
-
margin-bottom: 30px !important;
|
|
2070
|
-
}
|
|
2071
|
-
.responsive-row[data-mobile-wrap="true"][data-gap="40px"] .child-cell:not(:last-child) {
|
|
2072
|
-
margin-bottom: 40px !important;
|
|
2073
|
-
}
|
|
2217
|
+
${["10px", "15px", "20px", "24px", "30px", "40px", ...rowGaps]
|
|
2218
|
+
.filter((gap, index, self) => self.indexOf(gap) === index)
|
|
2219
|
+
.map((gap) => `
|
|
2220
|
+
.row-content-table[data-mobile-wrap="true"][data-gap="${gap}"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2221
|
+
margin-bottom: ${gap} !important;
|
|
2222
|
+
}`)
|
|
2223
|
+
.join("\n")}
|
|
2074
2224
|
}
|
|
2075
2225
|
|
|
2076
2226
|
/* ================================================= */
|
|
@@ -2150,7 +2300,7 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2150
2300
|
}
|
|
2151
2301
|
|
|
2152
2302
|
function Heading({ config, devMode, children }) {
|
|
2153
|
-
const { text, level = "h1", padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, } = config;
|
|
2303
|
+
const { text, level = "h1", padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, wordBreak, whiteSpace, } = config;
|
|
2154
2304
|
// Determine the content to render
|
|
2155
2305
|
const content = text !== null && text !== void 0 ? text : children;
|
|
2156
2306
|
const isString = typeof content === "string";
|
|
@@ -2173,6 +2323,8 @@ function Heading({ config, devMode, children }) {
|
|
|
2173
2323
|
textTransform: textTransform,
|
|
2174
2324
|
textDecoration: textDecoration,
|
|
2175
2325
|
direction: direction,
|
|
2326
|
+
wordBreak: wordBreak,
|
|
2327
|
+
whiteSpace: whiteSpace,
|
|
2176
2328
|
// Critical: Remove default top/bottom margin from HTML heading tags
|
|
2177
2329
|
margin: "0",
|
|
2178
2330
|
padding: "0",
|
|
@@ -2212,22 +2364,53 @@ function Html({ children, backgroundColor = "#ffffff", }) {
|
|
|
2212
2364
|
);
|
|
2213
2365
|
}
|
|
2214
2366
|
|
|
2367
|
+
function getBorderStyle$3(border) {
|
|
2368
|
+
if (!border)
|
|
2369
|
+
return {};
|
|
2370
|
+
const style = {};
|
|
2371
|
+
// If a full border is specified, apply it
|
|
2372
|
+
if (border.width && border.style && border.color) {
|
|
2373
|
+
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2374
|
+
}
|
|
2375
|
+
else {
|
|
2376
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
2377
|
+
// to prevent Outlook Classic from showing black borders
|
|
2378
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2379
|
+
if (hasIndividualBorders) {
|
|
2380
|
+
// Default all borders to none
|
|
2381
|
+
style.borderTop = "none";
|
|
2382
|
+
style.borderRight = "none";
|
|
2383
|
+
style.borderBottom = "none";
|
|
2384
|
+
style.borderLeft = "none";
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
// Override with specific borders if provided
|
|
2388
|
+
if (border.top) {
|
|
2389
|
+
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2390
|
+
}
|
|
2391
|
+
if (border.right) {
|
|
2392
|
+
style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
|
|
2393
|
+
}
|
|
2394
|
+
if (border.bottom) {
|
|
2395
|
+
style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
|
|
2396
|
+
}
|
|
2397
|
+
if (border.left) {
|
|
2398
|
+
style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
|
|
2399
|
+
}
|
|
2400
|
+
return style;
|
|
2401
|
+
}
|
|
2215
2402
|
function Image({ config, devNode, devMode }) {
|
|
2216
|
-
const { src, alt, width, height, maxHeight, maxWidth, backgroundColor, padding, borderRadius, href, target, } = config;
|
|
2403
|
+
const { src, alt, width, height, maxHeight, maxWidth, backgroundColor, padding, borderRadius, border, href, target, } = config;
|
|
2404
|
+
// Get border styles
|
|
2405
|
+
const borderStyle = getBorderStyle$3(border);
|
|
2217
2406
|
// 1. Image Style: Critical for compatibility, especially display: block
|
|
2218
|
-
const imgStyle = {
|
|
2407
|
+
const imgStyle = Object.assign({
|
|
2219
2408
|
// Basic image properties
|
|
2220
|
-
display: "block",
|
|
2221
|
-
objectFit: "cover", // For controlling how the image fits (modern CSS, may be ignored)
|
|
2409
|
+
display: "block", objectFit: "cover",
|
|
2222
2410
|
// Dimensions (using CSS fallback)
|
|
2223
|
-
width: width || "100%",
|
|
2224
|
-
height: height || "auto",
|
|
2225
|
-
maxWidth: maxWidth || "100%",
|
|
2226
|
-
maxHeight: maxHeight,
|
|
2411
|
+
width: width || "100%", height: height || "auto", maxWidth: maxWidth || "100%", maxHeight: maxHeight,
|
|
2227
2412
|
// Styling
|
|
2228
|
-
border: "0",
|
|
2229
|
-
borderRadius: borderRadius,
|
|
2230
|
-
};
|
|
2413
|
+
border: "0", borderRadius: borderRadius }, borderStyle);
|
|
2231
2414
|
// 2. Link Style: Ensure no underline or color changes
|
|
2232
2415
|
const linkStyle = {
|
|
2233
2416
|
display: "block",
|
|
@@ -2279,13 +2462,27 @@ const alignMap = {
|
|
|
2279
2462
|
center: "middle",
|
|
2280
2463
|
end: "bottom",
|
|
2281
2464
|
};
|
|
2282
|
-
function getBorderStyle$
|
|
2465
|
+
function getBorderStyle$2(border) {
|
|
2283
2466
|
if (!border)
|
|
2284
2467
|
return {};
|
|
2285
2468
|
const style = {};
|
|
2469
|
+
// If a full border is specified, apply it
|
|
2286
2470
|
if (border.width && border.style && border.color) {
|
|
2287
2471
|
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2288
2472
|
}
|
|
2473
|
+
else {
|
|
2474
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
2475
|
+
// to prevent Outlook Classic from showing black borders
|
|
2476
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2477
|
+
if (hasIndividualBorders) {
|
|
2478
|
+
// Default all borders to none
|
|
2479
|
+
style.borderTop = "none";
|
|
2480
|
+
style.borderRight = "none";
|
|
2481
|
+
style.borderBottom = "none";
|
|
2482
|
+
style.borderLeft = "none";
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
// Override with specific borders if provided
|
|
2289
2486
|
if (border.top) {
|
|
2290
2487
|
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2291
2488
|
}
|
|
@@ -2300,23 +2497,50 @@ function getBorderStyle$1(border) {
|
|
|
2300
2497
|
}
|
|
2301
2498
|
return style;
|
|
2302
2499
|
}
|
|
2303
|
-
function
|
|
2304
|
-
|
|
2500
|
+
function getHrefFromInnerLink(innerLink) {
|
|
2501
|
+
if (!innerLink || innerLink.type === "none")
|
|
2502
|
+
return undefined;
|
|
2503
|
+
switch (innerLink.type) {
|
|
2504
|
+
case "url":
|
|
2505
|
+
return innerLink.url;
|
|
2506
|
+
case "email":
|
|
2507
|
+
return innerLink.email ? `mailto:${innerLink.email}` : undefined;
|
|
2508
|
+
case "phone":
|
|
2509
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : undefined;
|
|
2510
|
+
case "anchor":
|
|
2511
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : undefined;
|
|
2512
|
+
case "page_top":
|
|
2513
|
+
return "#";
|
|
2514
|
+
case "page_bottom":
|
|
2515
|
+
return "#bottom";
|
|
2516
|
+
default:
|
|
2517
|
+
return undefined;
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
function Row({ children, config, devNode, devMode }) {
|
|
2521
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2305
2522
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2306
2523
|
const numChildren = childrenArray.length;
|
|
2307
|
-
|
|
2524
|
+
const href = getHrefFromInnerLink(config.innerLink);
|
|
2525
|
+
const target = (_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target;
|
|
2526
|
+
// 1. Outer TD for Background and Border Radius (no border here).
|
|
2527
|
+
// height declared here is the *total* outer height.
|
|
2308
2528
|
const backgroundTdStyle = Object.assign({ backgroundColor: config.backgroundColor, borderRadius: config.borderRadius, width: config.width || "100%", height: config.height,
|
|
2309
2529
|
// Background Image styles
|
|
2310
2530
|
backgroundImage: config.backgroundImage
|
|
2311
2531
|
? `url(${config.backgroundImage.src})`
|
|
2312
|
-
: undefined, backgroundRepeat: (
|
|
2313
|
-
// 2. Inner Table for Border and Border Radius
|
|
2314
|
-
|
|
2315
|
-
|
|
2532
|
+
: undefined, backgroundRepeat: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.repeat, backgroundSize: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size, backgroundPosition: (_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position }, (config.borderRadius && { overflow: "hidden" }));
|
|
2533
|
+
// 2. Inner Table for Border and Border Radius.
|
|
2534
|
+
// height: 100% so it stretches to fill the outer TD.
|
|
2535
|
+
const borderTableStyle = Object.assign({ width: "100%", height: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: config.borderRadius }, getBorderStyle$2(config.border));
|
|
2536
|
+
// 3. TD for Padding only — no height.
|
|
2537
|
+
// The outer TD owns the total height; setting height here would cause
|
|
2538
|
+
// browsers/email clients to treat it as content-box height and add
|
|
2539
|
+
// padding on top, making the row taller than the declared height.
|
|
2316
2540
|
const paddingTdStyle = {
|
|
2317
2541
|
padding: config.padding,
|
|
2318
2542
|
width: "100%",
|
|
2319
|
-
height
|
|
2543
|
+
// height intentionally omitted — padding must be inner, not additive
|
|
2320
2544
|
verticalAlign: "top",
|
|
2321
2545
|
};
|
|
2322
2546
|
// 4. Content Table - horizontal layout
|
|
@@ -2337,32 +2561,56 @@ function Row({ children, config, devNode }) {
|
|
|
2337
2561
|
? justifyMap$1[config.justifyContent]
|
|
2338
2562
|
: "left";
|
|
2339
2563
|
const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
|
|
2340
|
-
|
|
2564
|
+
// Content to render - wrapped in anchor if innerLink is defined
|
|
2565
|
+
const content = (jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2341
2566
|
position: "relative",
|
|
2342
2567
|
width: config.width || "100%",
|
|
2343
2568
|
height: config.height,
|
|
2344
2569
|
borderCollapse: "collapse",
|
|
2345
|
-
} }, (config.height && { height: config.height }), {
|
|
2570
|
+
} }, (config.height && { height: config.height }), { children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", Object.assign({ style: backgroundTdStyle }, (config.height && { height: config.height }), { children: jsxRuntime.jsx("table", { "aria-label": "Row Border Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: borderTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: paddingTdStyle, children: jsxRuntime.jsx("table", { "aria-label": "Row Justification Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2346
2571
|
width: "100%",
|
|
2347
2572
|
height: "100%",
|
|
2348
2573
|
borderCollapse: "collapse",
|
|
2349
|
-
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: tdAlign, children: jsxRuntime.jsx("table", Object.assign({ "aria-label": "Row Content", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: contentTableStyle }, (config.height && { height: config.height }), { className: "content-table", children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { className: "content-tr", children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("td", { valign: tdValign, style: {
|
|
2574
|
+
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: tdAlign, children: jsxRuntime.jsx("table", Object.assign({ "aria-label": "Row Content", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: contentTableStyle }, (config.height && { height: config.height }), { className: "content-table row-content-table", "data-mobile-justify": (_e = config.mobile) === null || _e === void 0 ? void 0 : _e.justifyContent, "data-mobile-align": (_f = config.mobile) === null || _f === void 0 ? void 0 : _f.alignItems, "data-mobile-wrap": ((_g = config.mobile) === null || _g === void 0 ? void 0 : _g.wrap) ? "true" : undefined, "data-gap": config.gap, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { className: "content-tr", children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("td", { valign: tdValign, style: {
|
|
2350
2575
|
verticalAlign: tdValign,
|
|
2351
2576
|
textAlign: "left",
|
|
2352
2577
|
padding: "0",
|
|
2353
2578
|
margin: "0",
|
|
2354
2579
|
}, className: "child-cell", children: child }), index < numChildren - 1 &&
|
|
2355
2580
|
config.gap && (jsxRuntime.jsx("td", { width: config.gap, style: gapTdStyle, className: "row-gap-td", children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) })) }) }) }) }) }) }) }) }) })) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
|
|
2581
|
+
// Wrap in anchor tag if innerLink is defined and NOT in dev mode
|
|
2582
|
+
if (href && !devMode) {
|
|
2583
|
+
return (jsxRuntime.jsx("a", Object.assign({ href: href }, (target && { target }), { style: {
|
|
2584
|
+
textDecoration: "none",
|
|
2585
|
+
color: "inherit",
|
|
2586
|
+
display: "block",
|
|
2587
|
+
}, children: content })));
|
|
2588
|
+
}
|
|
2589
|
+
return content;
|
|
2356
2590
|
}
|
|
2357
2591
|
var Row_default = React.memo(Row, arePropsEqual);
|
|
2358
2592
|
|
|
2359
|
-
function getBorderStyle(border) {
|
|
2593
|
+
function getBorderStyle$1(border) {
|
|
2360
2594
|
if (!border)
|
|
2361
2595
|
return {};
|
|
2362
2596
|
const style = {};
|
|
2597
|
+
// If a full border is specified, apply it
|
|
2363
2598
|
if (border.width && border.style && border.color) {
|
|
2364
2599
|
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2365
2600
|
}
|
|
2601
|
+
else {
|
|
2602
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
2603
|
+
// to prevent Outlook Classic from showing black borders
|
|
2604
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2605
|
+
if (hasIndividualBorders) {
|
|
2606
|
+
// Default all borders to none
|
|
2607
|
+
style.borderTop = "none";
|
|
2608
|
+
style.borderRight = "none";
|
|
2609
|
+
style.borderBottom = "none";
|
|
2610
|
+
style.borderLeft = "none";
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
// Override with specific borders if provided
|
|
2366
2614
|
if (border.top) {
|
|
2367
2615
|
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2368
2616
|
}
|
|
@@ -2380,7 +2628,7 @@ function getBorderStyle(border) {
|
|
|
2380
2628
|
const Section = ({ config, children, devNode, }) => {
|
|
2381
2629
|
var _a, _b, _c;
|
|
2382
2630
|
const { sectionType, padding } = config;
|
|
2383
|
-
return (jsxRuntime.jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign(Object.assign({ position: "relative", width: "100%", backgroundColor: config.backgroundColor }, getBorderStyle(config.border)), { backgroundImage: config.backgroundImage
|
|
2631
|
+
return (jsxRuntime.jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign(Object.assign({ position: "relative", width: "100%", backgroundColor: config.backgroundColor }, getBorderStyle$1(config.border)), { backgroundImage: config.backgroundImage
|
|
2384
2632
|
? `url(${config.backgroundImage.src})`
|
|
2385
2633
|
: undefined, backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat, backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size, backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position }), children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
|
|
2386
2634
|
padding: padding,
|
|
@@ -2397,7 +2645,7 @@ const Section = ({ config, children, devNode, }) => {
|
|
|
2397
2645
|
var Section_default = React.memo(Section, arePropsEqual);
|
|
2398
2646
|
|
|
2399
2647
|
function Spacer({ config, devNode }) {
|
|
2400
|
-
const { height } = config;
|
|
2648
|
+
const { height, hideOnMobile } = config;
|
|
2401
2649
|
// 1. Spacer Table Style
|
|
2402
2650
|
const spacerTableStyle = {
|
|
2403
2651
|
// Crucial for compatibility: Ensures no background or border interference
|
|
@@ -2405,7 +2653,6 @@ function Spacer({ config, devNode }) {
|
|
|
2405
2653
|
borderCollapse: "collapse",
|
|
2406
2654
|
border: "0",
|
|
2407
2655
|
width: "100%",
|
|
2408
|
-
// ✅ FIX: Use string literal indexing for MSO properties
|
|
2409
2656
|
// Note the CSS standard dash convention: 'mso-table-lspace'
|
|
2410
2657
|
// ["mso-table-lspace" as string]: "0pt",
|
|
2411
2658
|
["msoTableLspace"]: "0pt",
|
|
@@ -2426,14 +2673,14 @@ function Spacer({ config, devNode }) {
|
|
|
2426
2673
|
// Outer table ensures the spacer spans the full width of its container
|
|
2427
2674
|
jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: Object.assign({
|
|
2428
2675
|
// --- Start dev
|
|
2429
|
-
position: "relative" }, spacerTableStyle) }, { height: spacerHeightAttribute }, { children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle,
|
|
2676
|
+
position: "relative" }, spacerTableStyle) }, { height: spacerHeightAttribute }, { className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle,
|
|
2430
2677
|
// Explicit height attribute
|
|
2431
2678
|
height: spacerHeightAttribute, children: "\u00A0" }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
|
|
2432
2679
|
}
|
|
2433
2680
|
var Spacer_default = React.memo(Spacer, arePropsEqual);
|
|
2434
2681
|
|
|
2435
2682
|
function Text({ config, devMode, children }) {
|
|
2436
|
-
const { text, padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, } = config;
|
|
2683
|
+
const { text, padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", } = config;
|
|
2437
2684
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
2438
2685
|
const tdStyle = {
|
|
2439
2686
|
padding: padding,
|
|
@@ -2456,6 +2703,7 @@ function Text({ config, devMode, children }) {
|
|
|
2456
2703
|
verticalAlign: verticalAlign,
|
|
2457
2704
|
opacity: opacity,
|
|
2458
2705
|
whiteSpace: whiteSpace,
|
|
2706
|
+
wordBreak: wordBreak,
|
|
2459
2707
|
margin: "0",
|
|
2460
2708
|
padding: "0",
|
|
2461
2709
|
fontFamily: "Arial, Helvetica, sans-serif",
|
|
@@ -2476,18 +2724,96 @@ const justifyMap = {
|
|
|
2476
2724
|
center: "center",
|
|
2477
2725
|
end: "right",
|
|
2478
2726
|
};
|
|
2727
|
+
function getBorderStyle(border) {
|
|
2728
|
+
if (!border)
|
|
2729
|
+
return {};
|
|
2730
|
+
const style = {};
|
|
2731
|
+
// If a full border is specified, apply it
|
|
2732
|
+
if (border.width && border.style && border.color) {
|
|
2733
|
+
style.border = `${border.width} ${border.style} ${border.color}`;
|
|
2734
|
+
}
|
|
2735
|
+
else {
|
|
2736
|
+
// If only individual borders are specified, explicitly set others to 'none'
|
|
2737
|
+
// to prevent Outlook Classic from showing black borders
|
|
2738
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2739
|
+
if (hasIndividualBorders) {
|
|
2740
|
+
// Default all borders to none
|
|
2741
|
+
style.borderTop = "none";
|
|
2742
|
+
style.borderRight = "none";
|
|
2743
|
+
style.borderBottom = "none";
|
|
2744
|
+
style.borderLeft = "none";
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
// Override with specific borders if provided
|
|
2748
|
+
if (border.top) {
|
|
2749
|
+
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
2750
|
+
}
|
|
2751
|
+
if (border.right) {
|
|
2752
|
+
style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
|
|
2753
|
+
}
|
|
2754
|
+
if (border.bottom) {
|
|
2755
|
+
style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
|
|
2756
|
+
}
|
|
2757
|
+
if (border.left) {
|
|
2758
|
+
style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
|
|
2759
|
+
}
|
|
2760
|
+
return style;
|
|
2761
|
+
}
|
|
2762
|
+
function getBorderStyleString(border) {
|
|
2763
|
+
if (!border)
|
|
2764
|
+
return "";
|
|
2765
|
+
const styles = [];
|
|
2766
|
+
// If a full border is specified, apply it
|
|
2767
|
+
if (border.width && border.style && border.color) {
|
|
2768
|
+
styles.push(`border: ${border.width} ${border.style} ${border.color};`);
|
|
2769
|
+
}
|
|
2770
|
+
else {
|
|
2771
|
+
// If only individual borders are specified
|
|
2772
|
+
const hasIndividualBorders = border.top || border.right || border.bottom || border.left;
|
|
2773
|
+
if (hasIndividualBorders) {
|
|
2774
|
+
// Default all borders to none
|
|
2775
|
+
styles.push("border-top: none;");
|
|
2776
|
+
styles.push("border-right: none;");
|
|
2777
|
+
styles.push("border-bottom: none;");
|
|
2778
|
+
styles.push("border-left: none;");
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
// Override with specific borders if provided
|
|
2782
|
+
if (border.top) {
|
|
2783
|
+
styles.push(`border-top: ${border.top.width} ${border.top.style} ${border.top.color};`);
|
|
2784
|
+
}
|
|
2785
|
+
if (border.right) {
|
|
2786
|
+
styles.push(`border-right: ${border.right.width} ${border.right.style} ${border.right.color};`);
|
|
2787
|
+
}
|
|
2788
|
+
if (border.bottom) {
|
|
2789
|
+
styles.push(`border-bottom: ${border.bottom.width} ${border.bottom.style} ${border.bottom.color};`);
|
|
2790
|
+
}
|
|
2791
|
+
if (border.left) {
|
|
2792
|
+
styles.push(`border-left: ${border.left.width} ${border.left.style} ${border.left.color};`);
|
|
2793
|
+
}
|
|
2794
|
+
return styles.join(" ");
|
|
2795
|
+
}
|
|
2479
2796
|
// Helper to build Iconify API URL
|
|
2480
2797
|
function buildIconifyUrl(config) {
|
|
2481
2798
|
const { iconIdentifier, height = 24, color = "000000", rotate = 0, rotateOrientation = "cw", } = config;
|
|
2482
2799
|
if (!iconIdentifier)
|
|
2483
2800
|
return null;
|
|
2801
|
+
// Parse height to extract numeric value
|
|
2802
|
+
const parseHeight = (h) => {
|
|
2803
|
+
if (typeof h === "number")
|
|
2804
|
+
return h;
|
|
2805
|
+
// Extract numeric value from string (e.g., "24px" -> 24)
|
|
2806
|
+
const match = String(h).match(/^(-?\d*\.?\d+)/);
|
|
2807
|
+
return match ? parseFloat(match[1]) : 24;
|
|
2808
|
+
};
|
|
2809
|
+
const numericHeight = parseHeight(height);
|
|
2484
2810
|
// Remove # from color if present
|
|
2485
2811
|
const cleanColor = color.replace("#", "");
|
|
2486
2812
|
// Build URL from template
|
|
2487
2813
|
const template = process.env.ICONIFY_API_IMAGE_URI ||
|
|
2488
2814
|
"https://iconify.pagenflow.com/api/image/{{height}}/{{color}}/{{rotate}}-{{rotate-orientation}}/{{icon-full-name}}.png";
|
|
2489
2815
|
return template
|
|
2490
|
-
.replace("{{height}}", String(
|
|
2816
|
+
.replace("{{height}}", String(numericHeight * 2))
|
|
2491
2817
|
.replace("{{color}}", cleanColor)
|
|
2492
2818
|
.replace("{{rotate}}", String(rotate))
|
|
2493
2819
|
.replace("{{rotate-orientation}}", rotateOrientation)
|
|
@@ -2517,12 +2843,15 @@ function buildLinkHref(innerLink) {
|
|
|
2517
2843
|
function Icon({ config, devNode, devMode, children }) {
|
|
2518
2844
|
const {
|
|
2519
2845
|
// base64Source,
|
|
2520
|
-
width, height, backgroundColor, padding = "0", borderRadius = "0", innerLink, justifyContent = "center", } = config;
|
|
2846
|
+
width, height, backgroundColor, padding = "0", borderRadius = "0", border, innerLink, justifyContent = "center", } = config;
|
|
2521
2847
|
// Determine icon source
|
|
2522
2848
|
const iconSrc = buildIconifyUrl(config);
|
|
2523
2849
|
const href = buildLinkHref(innerLink);
|
|
2524
2850
|
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_self";
|
|
2525
2851
|
const align = justifyMap[justifyContent];
|
|
2852
|
+
// Get border styles
|
|
2853
|
+
const borderStyle = getBorderStyle(border);
|
|
2854
|
+
const borderStyleString = getBorderStyleString(border);
|
|
2526
2855
|
// Convert width/height to string with px if number
|
|
2527
2856
|
const widthStr = typeof width === "number" ? `${width}px` : width;
|
|
2528
2857
|
const heightStr = typeof height === "number" ? `${height}px` : height;
|
|
@@ -2543,6 +2872,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2543
2872
|
border: 0, // No default border
|
|
2544
2873
|
width: widthStr || "auto",
|
|
2545
2874
|
height: heightStr || "auto",
|
|
2875
|
+
objectFit: "contain",
|
|
2546
2876
|
};
|
|
2547
2877
|
// 2. Link Style: No underline or color changes
|
|
2548
2878
|
const linkStyle = {
|
|
@@ -2551,14 +2881,21 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2551
2881
|
border: 0,
|
|
2552
2882
|
outline: "none",
|
|
2553
2883
|
};
|
|
2554
|
-
// 3. TD Style:
|
|
2555
|
-
const
|
|
2556
|
-
padding: padding,
|
|
2884
|
+
// 3. Outer TD Style: Background and border-radius wrapper with border
|
|
2885
|
+
const outerTdStyle = {
|
|
2557
2886
|
backgroundColor: backgroundColor,
|
|
2558
|
-
fontSize: "0", // CRITICAL: Collapses extra space
|
|
2559
|
-
lineHeight: "0", // CRITICAL: Collapses extra space7
|
|
2560
2887
|
borderRadius: borderRadius,
|
|
2561
2888
|
overflow: "hidden",
|
|
2889
|
+
fontSize: "0",
|
|
2890
|
+
lineHeight: "0",
|
|
2891
|
+
};
|
|
2892
|
+
// 4. Inner Table Style: Apply border here with border-collapse: separate
|
|
2893
|
+
const innerTableStyle = Object.assign({ width: "100%", borderCollapse: "separate", borderSpacing: 0, borderRadius: borderRadius }, borderStyle);
|
|
2894
|
+
// 5. Inner TD Style: Padding
|
|
2895
|
+
const innerTdStyle = {
|
|
2896
|
+
padding: padding,
|
|
2897
|
+
fontSize: "0", // CRITICAL: Collapses extra space
|
|
2898
|
+
lineHeight: "0", // CRITICAL: Collapses extra space
|
|
2562
2899
|
};
|
|
2563
2900
|
// --- VML Calculation for Outlook Compatibility ---
|
|
2564
2901
|
const numericPadding = parseInt(padding.split(" ")[0] || "0", 10);
|
|
@@ -2575,15 +2912,19 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2575
2912
|
const arcsize = numericBorderRadius > 0
|
|
2576
2913
|
? Math.min((numericBorderRadius / Math.min(vmlWidth, vmlHeight)) * 100, 100)
|
|
2577
2914
|
: 0;
|
|
2915
|
+
// VML stroke color for border
|
|
2916
|
+
const vmlStrokeColor = (border === null || border === void 0 ? void 0 : border.color) || vmlFillColor;
|
|
2917
|
+
const vmlStrokeWeight = (border === null || border === void 0 ? void 0 : border.width) ? parseInt(border.width, 10) : 0;
|
|
2918
|
+
const hasVmlStroke = vmlStrokeWeight > 0;
|
|
2578
2919
|
// Build VML code for Outlook
|
|
2579
2920
|
const vmlIcon = backgroundColor && numericBorderRadius > 0
|
|
2580
2921
|
? `
|
|
2581
2922
|
<!--[if mso]>
|
|
2582
|
-
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" ${href && !devMode ? `href="${href}"` : ""} style="height:${vmlHeight}px;width:${vmlWidth}px;v-text-anchor:middle;" arcsize="${arcsize}%" stroke="false" fillcolor="${vmlFillColor}">
|
|
2923
|
+
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" ${href && !devMode ? `href="${href}"` : ""} style="height:${vmlHeight}px;width:${vmlWidth}px;v-text-anchor:middle;" arcsize="${arcsize}%" ${hasVmlStroke ? `strokecolor="${vmlStrokeColor}" strokeweight="${vmlStrokeWeight}px"` : 'stroke="false"'} fillcolor="${vmlFillColor}">
|
|
2583
2924
|
<w:anchorlock/>
|
|
2584
2925
|
<v:textbox inset="0,0,0,0" style="text-align: center;">
|
|
2585
2926
|
<center style="padding:${padding};">
|
|
2586
|
-
<img src="${iconSrc || ""}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;" />
|
|
2927
|
+
<img src="${iconSrc || ""}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;object-fit:contain;" />
|
|
2587
2928
|
</center>
|
|
2588
2929
|
</v:textbox>
|
|
2589
2930
|
</v:roundrect>
|
|
@@ -2595,8 +2936,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2595
2936
|
return null;
|
|
2596
2937
|
}
|
|
2597
2938
|
// Icon image element
|
|
2598
|
-
const iconElement = devMode && !!children ? (children) : iconSrc ? (jsxRuntime.jsx("img", { draggable: false, src: iconSrc, alt: ""
|
|
2599
|
-
, style: imgStyle, width: widthNum, height: heightNum, border: 0 })) : (jsxRuntime.jsx(jsxRuntime.Fragment, {}));
|
|
2939
|
+
const iconElement = devMode && !!children ? (children) : iconSrc ? (jsxRuntime.jsx("img", { draggable: false, src: iconSrc, alt: "", style: imgStyle, width: widthNum, height: heightNum, border: 0 })) : (jsxRuntime.jsx(jsxRuntime.Fragment, {}));
|
|
2600
2940
|
// Wrap in link if href exists and not in dev mode
|
|
2601
2941
|
const content = href && !devMode ? (jsxRuntime.jsx("a", Object.assign({ href: href, target: target, style: linkStyle }, (target === "_blank" ? { rel: "noopener noreferrer" } : {}), { children: iconElement }))) : (iconElement);
|
|
2602
2942
|
// Build the HTML content with VML support (only when NOT in dev mode)
|
|
@@ -2608,12 +2948,20 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2608
2948
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
|
|
2609
2949
|
<tbody>
|
|
2610
2950
|
<tr>
|
|
2611
|
-
<td style="background-color: ${backgroundColor}; border-radius: ${borderRadius};
|
|
2612
|
-
${
|
|
2951
|
+
<td style="background-color: ${backgroundColor}; border-radius: ${borderRadius}; overflow: hidden; font-size: 0; line-height: 0;">
|
|
2952
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}; width: 100%; ${borderStyleString}">
|
|
2953
|
+
<tbody>
|
|
2954
|
+
<tr>
|
|
2955
|
+
<td style="padding: ${padding}; font-size: 0; line-height: 0;">
|
|
2956
|
+
${href
|
|
2613
2957
|
? `<a href="${href}" target="${target}" style="display:block;text-decoration:none;border:0;outline:none;" ${target === "_blank" ? 'rel="noopener noreferrer"' : ""}>
|
|
2614
|
-
|
|
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"};" />`}
|
|
2958
|
+
<img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};object-fit:contain;" />
|
|
2959
|
+
</a>`
|
|
2960
|
+
: `<img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};object-fit:contain;" />`}
|
|
2961
|
+
</td>
|
|
2962
|
+
</tr>
|
|
2963
|
+
</tbody>
|
|
2964
|
+
</table>
|
|
2617
2965
|
</td>
|
|
2618
2966
|
</tr>
|
|
2619
2967
|
</tbody>
|
|
@@ -2625,7 +2973,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2625
2973
|
// --- Start dev
|
|
2626
2974
|
position: "relative",
|
|
2627
2975
|
// --- End dev
|
|
2628
|
-
width:
|
|
2976
|
+
width: "auto",
|
|
2629
2977
|
borderCollapse: "collapse",
|
|
2630
2978
|
// base
|
|
2631
2979
|
boxSizing: "border-box",
|
|
@@ -2634,7 +2982,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2634
2982
|
padding: 0,
|
|
2635
2983
|
}, onClick: devMode ? (e) => e.preventDefault() : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: useVML ? (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
|
|
2636
2984
|
__html: htmlContent !== null && htmlContent !== void 0 ? htmlContent : "",
|
|
2637
|
-
} })) : (jsxRuntime.jsx("td", { style:
|
|
2985
|
+
} })) : (jsxRuntime.jsx("td", { style: outerTdStyle, align: align, children: jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: innerTdStyle, align: align, children: content }) }) }) }) })) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
|
|
2638
2986
|
}
|
|
2639
2987
|
var Icon_default = React.memo(Icon, arePropsEqual);
|
|
2640
2988
|
|