@pagenflow/email 1.4.2 → 1.4.4
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/Body.js +57 -0
- package/dist/components/BodyDev.js +57 -0
- package/dist/components/Button.d.ts +3 -2
- package/dist/components/Button.js +327 -0
- package/dist/components/Column.js +127 -0
- package/dist/components/Container.js +179 -0
- package/dist/components/Divider.d.ts +0 -5
- package/dist/components/Divider.js +41 -0
- package/dist/components/Font.js +44 -0
- package/dist/components/Head.js +134 -0
- package/dist/components/HeadDev.js +311 -0
- package/dist/components/Heading.js +46 -0
- package/dist/components/Html.js +20 -0
- package/dist/components/Icon.js +276 -0
- package/dist/components/Image.d.ts +7 -2
- package/dist/components/Image.js +119 -0
- package/dist/components/MsoConditional.js +19 -0
- package/dist/components/Row.js +157 -0
- package/dist/components/Section.js +65 -0
- package/dist/components/Spacer.js +40 -0
- package/dist/components/Text.js +42 -0
- package/dist/index.cjs.js +362 -167
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +362 -167
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +17 -0
- package/dist/types/IInnerLink.js +1 -0
- package/dist/types/ResolvedFont.js +1 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/isEqual.js +1439 -0
- package/dist/utils/memoUtils.js +55 -0
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -15,24 +15,42 @@ function Body({ children, config = {} }) {
|
|
|
15
15
|
const bgSize = ((_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size) || "cover";
|
|
16
16
|
const bgPosition = ((_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position) || "center";
|
|
17
17
|
// 1. Style for the <body> tag inline
|
|
18
|
-
const bodyStyle =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
const bodyStyle = {
|
|
19
|
+
backgroundColor: globalBackgroundColor,
|
|
20
|
+
color: globalColor,
|
|
21
|
+
fontSize: globalFontSize,
|
|
22
|
+
lineHeight: globalLineHeight,
|
|
23
|
+
padding: "0",
|
|
24
|
+
margin: "0",
|
|
25
|
+
WebkitTextSizeAdjust: "100%",
|
|
26
|
+
overflowX: "hidden",
|
|
27
|
+
["msTextSizeAdjust"]: "100%",
|
|
28
|
+
["msoLineHeightRule"]: "exactly",
|
|
29
|
+
fontFamily: globalFontFamily,
|
|
30
|
+
// Background image support (if provided)
|
|
31
|
+
...(bgImage && {
|
|
32
|
+
backgroundImage: `url(${bgImage})`,
|
|
33
|
+
backgroundRepeat: bgRepeat,
|
|
34
|
+
backgroundSize: bgSize,
|
|
35
|
+
backgroundPosition: bgPosition,
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
24
38
|
// 2. Style for the top-level <table> wrapper
|
|
25
39
|
const outerTableStyle = {
|
|
26
40
|
width: "100%",
|
|
27
41
|
["msoLineHeightRule"]: "exactly",
|
|
28
42
|
borderCollapse: "collapse",
|
|
29
43
|
};
|
|
30
|
-
return (jsxs("body", { style: bodyStyle, children: [jsx("center", { style:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
return (jsxs("body", { style: bodyStyle, children: [jsx("center", { style: {
|
|
45
|
+
width: "100%",
|
|
46
|
+
background: globalBackgroundColor,
|
|
47
|
+
...(bgImage && {
|
|
48
|
+
backgroundImage: `url(${bgImage})`,
|
|
49
|
+
backgroundRepeat: bgRepeat,
|
|
50
|
+
backgroundSize: bgSize,
|
|
51
|
+
backgroundPosition: bgPosition,
|
|
52
|
+
}),
|
|
53
|
+
}, children: jsx("table", { role: "presentation", border: 0, cellPadding: 0, cellSpacing: 0, align: "center", width: "100%", style: outerTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { align: "center", style: { padding: "0", margin: "0" }, children: children }) }) }) }) }), jsx("div", { style: {
|
|
36
54
|
display: "none",
|
|
37
55
|
whiteSpace: "nowrap",
|
|
38
56
|
font: "15px courier",
|
|
@@ -1519,40 +1537,26 @@ const justifyMap$3 = {
|
|
|
1519
1537
|
center: "center",
|
|
1520
1538
|
end: "right",
|
|
1521
1539
|
};
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
}
|
|
1542
|
-
// Override with specific borders if provided
|
|
1543
|
-
if (border.top) {
|
|
1544
|
-
style.borderTop = `${border.top.width} ${border.top.style} ${border.top.color}`;
|
|
1545
|
-
}
|
|
1546
|
-
if (border.right) {
|
|
1547
|
-
style.borderRight = `${border.right.width} ${border.right.style} ${border.right.color}`;
|
|
1548
|
-
}
|
|
1549
|
-
if (border.bottom) {
|
|
1550
|
-
style.borderBottom = `${border.bottom.width} ${border.bottom.style} ${border.bottom.color}`;
|
|
1551
|
-
}
|
|
1552
|
-
if (border.left) {
|
|
1553
|
-
style.borderLeft = `${border.left.width} ${border.left.style} ${border.left.color}`;
|
|
1540
|
+
// Helper to build link href based on innerLink type (mirrors Icon component)
|
|
1541
|
+
function buildLinkHref$2(innerLink) {
|
|
1542
|
+
if (!innerLink || innerLink.type === "none")
|
|
1543
|
+
return null;
|
|
1544
|
+
switch (innerLink.type) {
|
|
1545
|
+
case "url":
|
|
1546
|
+
return innerLink.url || null;
|
|
1547
|
+
case "email":
|
|
1548
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
1549
|
+
case "phone":
|
|
1550
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
1551
|
+
case "anchor":
|
|
1552
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
1553
|
+
case "page_top":
|
|
1554
|
+
return "#top";
|
|
1555
|
+
case "page_bottom":
|
|
1556
|
+
return "#bottom";
|
|
1557
|
+
default:
|
|
1558
|
+
return null;
|
|
1554
1559
|
}
|
|
1555
|
-
return style;
|
|
1556
1560
|
}
|
|
1557
1561
|
function getBorderStyleString$2(border) {
|
|
1558
1562
|
if (!border)
|
|
@@ -1589,38 +1593,48 @@ function getBorderStyleString$2(border) {
|
|
|
1589
1593
|
return styles.join(" ");
|
|
1590
1594
|
}
|
|
1591
1595
|
function Button({ config, devMode }) {
|
|
1592
|
-
const {
|
|
1593
|
-
|
|
1596
|
+
const { innerLink, children, backgroundColor, color, padding, borderRadius, border, width, maxWidth, justifyContent, textAlign, fontSize, fontWeight, fontStyle, fontFamily, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, opacity, whiteSpace, wordBreak, } = config;
|
|
1597
|
+
// Resolve href from innerLink
|
|
1598
|
+
const href = buildLinkHref$2(innerLink);
|
|
1599
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
1594
1600
|
// Sanitize fontFamily early so safeFontFamily is available for all paths below.
|
|
1595
1601
|
const safeFontFamily = fontFamily
|
|
1596
1602
|
? fontFamily.replace(/['"]/g, "")
|
|
1597
1603
|
: fontFamily;
|
|
1598
|
-
//
|
|
1599
|
-
const backgroundTdStyle =
|
|
1600
|
-
|
|
1601
|
-
|
|
1604
|
+
// Outer TD Style for Background and Border Radius (no border)
|
|
1605
|
+
const backgroundTdStyle = {
|
|
1606
|
+
backgroundColor: backgroundColor,
|
|
1607
|
+
borderRadius: borderRadius,
|
|
1608
|
+
width: width || "auto",
|
|
1609
|
+
...(maxWidth && { maxWidth: maxWidth }),
|
|
1610
|
+
// Overflow hidden to clip background to border-radius
|
|
1611
|
+
...(borderRadius && { overflow: "hidden" }),
|
|
1612
|
+
};
|
|
1613
|
+
// Border styles
|
|
1602
1614
|
const borderStyleString = getBorderStyleString$2(border);
|
|
1603
1615
|
// --- Determine Button Approach Based on Width ---
|
|
1604
1616
|
// Check if width is percentage-based or not defined
|
|
1605
1617
|
const isPercentageWidth = !width || width.includes("%");
|
|
1606
1618
|
const useSimpleOutlookApproach = isPercentageWidth;
|
|
1607
|
-
const align = justifyMap$3[justifyContent];
|
|
1619
|
+
const align = justifyContent ? justifyMap$3[justifyContent] : undefined;
|
|
1608
1620
|
// --- VML Calculation and Code for Outlook Compatibility (Fixed Width Only) ---
|
|
1609
1621
|
let vmlButton = "";
|
|
1610
1622
|
if (!useSimpleOutlookApproach) {
|
|
1611
1623
|
// VML needs fixed pixel height. We estimate it based on padding and potential wrapping.
|
|
1612
|
-
const numericPadding = parseInt(padding.split(" ")[0] || "12", 10);
|
|
1613
|
-
const numericFontSize = parseInt(fontSize, 10);
|
|
1614
|
-
const numericLineHeight = lineHeight
|
|
1615
|
-
?
|
|
1616
|
-
|
|
1624
|
+
const numericPadding = padding ? parseInt(padding.split(" ")[0] || "12", 10) : 12;
|
|
1625
|
+
const numericFontSize = fontSize ? parseInt(fontSize, 10) : 0;
|
|
1626
|
+
const numericLineHeight = lineHeight
|
|
1627
|
+
? lineHeight.includes("px")
|
|
1628
|
+
? parseInt(lineHeight, 10)
|
|
1629
|
+
: numericFontSize * parseFloat(lineHeight)
|
|
1630
|
+
: numericFontSize;
|
|
1617
1631
|
// Trust user's explicit pixel width - no calculation needed
|
|
1618
1632
|
const vmlWidth = parseInt(width, 10);
|
|
1619
1633
|
// Calculate VML height - trust user's padding and let text wrap naturally
|
|
1620
1634
|
// VML v:textbox will handle text wrapping automatically
|
|
1621
1635
|
const textContent = typeof children === "string" ? children : "";
|
|
1622
1636
|
// Estimate number of lines based on text length and button width
|
|
1623
|
-
const horizontalPadding = padding.split(" ")[1]
|
|
1637
|
+
const horizontalPadding = (padding === null || padding === void 0 ? void 0 : padding.split(" ")[1])
|
|
1624
1638
|
? parseInt(padding.split(" ")[1], 10) * 2
|
|
1625
1639
|
: numericPadding * 2;
|
|
1626
1640
|
const availableTextWidth = vmlWidth - horizontalPadding;
|
|
@@ -1633,15 +1647,17 @@ function Button({ config, devMode }) {
|
|
|
1633
1647
|
// Add extra 4px buffer to prevent bottom cropping in VML
|
|
1634
1648
|
const vmlHeight = Math.max(numericPadding * 2 + textHeight + 4, 40);
|
|
1635
1649
|
// VML colors must use the full hex format (e.g., #000000)
|
|
1636
|
-
const vmlFillColor = backgroundColor
|
|
1637
|
-
? backgroundColor
|
|
1638
|
-
|
|
1650
|
+
const vmlFillColor = backgroundColor
|
|
1651
|
+
? backgroundColor.startsWith("#")
|
|
1652
|
+
? backgroundColor
|
|
1653
|
+
: `#${backgroundColor}`
|
|
1654
|
+
: undefined;
|
|
1639
1655
|
// VML stroke color for border
|
|
1640
1656
|
const vmlStrokeColor = (border === null || border === void 0 ? void 0 : border.color) || vmlFillColor;
|
|
1641
1657
|
const vmlStrokeWeight = (border === null || border === void 0 ? void 0 : border.width) ? parseInt(border.width, 10) : 0;
|
|
1642
1658
|
const hasVmlStroke = vmlStrokeWeight > 0;
|
|
1643
1659
|
// Build VML font styles - consistent with other rendering paths
|
|
1644
|
-
const vmlFontWeight = fontWeight
|
|
1660
|
+
const vmlFontWeight = fontWeight;
|
|
1645
1661
|
const vmlFontStyle = fontStyle === "italic" ? "font-style:italic;" : "";
|
|
1646
1662
|
const vmlLetterSpacing = letterSpacing
|
|
1647
1663
|
? `letter-spacing:${letterSpacing};`
|
|
@@ -1652,12 +1668,12 @@ function Button({ config, devMode }) {
|
|
|
1652
1668
|
const vmlTextDecoration = textDecoration && textDecoration !== "none"
|
|
1653
1669
|
? `text-decoration:${textDecoration};`
|
|
1654
1670
|
: "";
|
|
1655
|
-
const vmlWhiteSpace = whiteSpace
|
|
1671
|
+
const vmlWhiteSpace = whiteSpace ? `white-space:${whiteSpace};` : "";
|
|
1656
1672
|
const vmlDirection = direction ? `direction:${direction};` : "";
|
|
1657
1673
|
const vmlOpacity = opacity !== undefined ? `opacity:${opacity};` : "";
|
|
1658
1674
|
// VML code uses MSO conditional comments to render only in Outlook
|
|
1659
1675
|
// Use table with explicit MSO height for vertical centering
|
|
1660
|
-
const horizontalPaddingValue = padding.split(" ")[1]
|
|
1676
|
+
const horizontalPaddingValue = (padding === null || padding === void 0 ? void 0 : padding.split(" ")[1])
|
|
1661
1677
|
? parseInt(padding.split(" ")[1], 10)
|
|
1662
1678
|
: numericPadding;
|
|
1663
1679
|
// For VML, we need to use a table inside to properly apply padding and centering
|
|
@@ -1666,7 +1682,7 @@ function Button({ config, devMode }) {
|
|
|
1666
1682
|
if (textAlign === "center") {
|
|
1667
1683
|
vmlAlignAttr = 'align="center"';
|
|
1668
1684
|
}
|
|
1669
|
-
else {
|
|
1685
|
+
else if (textAlign) {
|
|
1670
1686
|
vmlAlignStyle = `text-align:${textAlign};`;
|
|
1671
1687
|
}
|
|
1672
1688
|
// Border radius is intentionally omitted (arcsize="0%") for Outlook Classic.
|
|
@@ -1674,12 +1690,12 @@ function Button({ config, devMode }) {
|
|
|
1674
1690
|
// is inconsistent, so we render sharp corners there instead.
|
|
1675
1691
|
vmlButton = `
|
|
1676
1692
|
<!--[if mso]>
|
|
1677
|
-
<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="0%" strokecolor="${vmlStrokeColor}" ${hasVmlStroke ? `strokeweight="${vmlStrokeWeight}px"` : 'stroke="f"'} fillcolor="${vmlFillColor}">
|
|
1693
|
+
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" ${href ? `href="${href}"` : ""} style="height:${vmlHeight}px;width:${vmlWidth}px;" arcsize="0%" ${vmlStrokeColor ? `strokecolor="${vmlStrokeColor}"` : ""} ${hasVmlStroke ? `strokeweight="${vmlStrokeWeight}px"` : 'stroke="f"'} ${vmlFillColor ? `fillcolor="${vmlFillColor}"` : ""}>
|
|
1678
1694
|
<w:anchorlock/>
|
|
1679
1695
|
<v:textbox inset="${horizontalPaddingValue}px,${numericPadding}px,${horizontalPaddingValue}px,${numericPadding}px">
|
|
1680
1696
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse:collapse;">
|
|
1681
1697
|
<tr>
|
|
1682
|
-
<td ${vmlAlignAttr} valign="middle" style="${vmlAlignStyle}color:${color}
|
|
1698
|
+
<td ${vmlAlignAttr} valign="middle" style="${vmlAlignStyle}${color ? `color:${color};` : ""}${safeFontFamily ? `font-family:${safeFontFamily};` : ""}${fontSize ? `font-size:${fontSize};` : ""}${vmlFontWeight ? `font-weight:${vmlFontWeight};` : ""}${vmlFontStyle}${vmlLetterSpacing}${vmlTextTransform}${vmlTextDecoration}${vmlWhiteSpace}${vmlDirection}${vmlOpacity}${lineHeight ? `line-height:${lineHeight};` : ""}mso-line-height-rule:exactly;">
|
|
1683
1699
|
${typeof children === "string" ? children : ""}
|
|
1684
1700
|
</td>
|
|
1685
1701
|
</tr>
|
|
@@ -1703,10 +1719,10 @@ function Button({ config, devMode }) {
|
|
|
1703
1719
|
const textTransformProp = textTransform
|
|
1704
1720
|
? `text-transform: ${textTransform};`
|
|
1705
1721
|
: "";
|
|
1706
|
-
const whiteSpaceProp = whiteSpace
|
|
1722
|
+
const whiteSpaceProp = whiteSpace ? `white-space: ${whiteSpace};` : "";
|
|
1707
1723
|
const directionProp = direction ? `direction: ${direction};` : "";
|
|
1708
1724
|
const opacityProp = opacity !== undefined ? `opacity: ${opacity};` : "";
|
|
1709
|
-
const wordBreakProp = wordBreak
|
|
1725
|
+
const wordBreakProp = wordBreak ? `word-break: ${wordBreak};` : "";
|
|
1710
1726
|
// Border radius is intentionally omitted from the Outlook Classic table cell.
|
|
1711
1727
|
// Outlook Classic ignores border-radius on table cells anyway, and including it
|
|
1712
1728
|
// can cause unexpected rendering artifacts, so we explicitly leave it out.
|
|
@@ -1714,13 +1730,17 @@ function Button({ config, devMode }) {
|
|
|
1714
1730
|
<!--[if mso]>
|
|
1715
1731
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;">
|
|
1716
1732
|
<tr>
|
|
1717
|
-
<td align="${align}" style="padding: 0;">
|
|
1733
|
+
<td ${align ? `align="${align}"` : ""} style="padding: 0;">
|
|
1718
1734
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="${width || "auto"}" style="border-collapse: collapse;">
|
|
1719
1735
|
<tr>
|
|
1720
|
-
<td bgcolor="${backgroundColor}" align="${textAlign}" style="padding: ${padding}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1736
|
+
<td ${backgroundColor ? `bgcolor="${backgroundColor}"` : ""} ${textAlign ? `align="${textAlign}"` : ""} style="${padding ? `padding: ${padding};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${borderStyleString}">
|
|
1737
|
+
${href
|
|
1738
|
+
? `<a href="${href}" target="${target}" rel="noopener noreferrer" style="${color ? `color: ${color};` : ""} ${textDecorationStyle} display: block; ${safeFontFamily ? `font-family: ${safeFontFamily};` : ""} ${fontSize ? `font-size: ${fontSize};` : ""} ${fontWeight ? `font-weight: ${fontWeight};` : ""} ${fontStyleProp} ${lineHeight ? `line-height: ${lineHeight};` : ""} ${letterSpacingProp} ${textTransformProp} ${textAlign ? `text-align: ${textAlign};` : ""} ${whiteSpaceProp} ${directionProp} ${opacityProp} ${wordBreakProp} mso-line-height-rule: exactly;">
|
|
1739
|
+
${typeof children === "string" ? children : ""}
|
|
1740
|
+
</a>`
|
|
1741
|
+
: `<span style="${color ? `color: ${color};` : ""} ${textDecorationStyle} display: block; ${safeFontFamily ? `font-family: ${safeFontFamily};` : ""} ${fontSize ? `font-size: ${fontSize};` : ""} ${fontWeight ? `font-weight: ${fontWeight};` : ""} ${fontStyleProp} ${lineHeight ? `line-height: ${lineHeight};` : ""} ${letterSpacingProp} ${textTransformProp} ${textAlign ? `text-align: ${textAlign};` : ""} ${whiteSpaceProp} ${directionProp} ${opacityProp} ${wordBreakProp} mso-line-height-rule: exactly;">
|
|
1742
|
+
${typeof children === "string" ? children : ""}
|
|
1743
|
+
</span>`}
|
|
1724
1744
|
</td>
|
|
1725
1745
|
</tr>
|
|
1726
1746
|
</table>
|
|
@@ -1734,7 +1754,7 @@ function Button({ config, devMode }) {
|
|
|
1734
1754
|
// fontFamily uses the sanitized value so embedded quotes never break the
|
|
1735
1755
|
// style attribute string (which is always wrapped in double quotes).
|
|
1736
1756
|
const sharedTextStyles = [
|
|
1737
|
-
`color: ${color}
|
|
1757
|
+
color ? `color: ${color};` : "",
|
|
1738
1758
|
safeFontFamily ? `font-family: ${safeFontFamily};` : "",
|
|
1739
1759
|
fontSize ? `font-size: ${fontSize};` : "",
|
|
1740
1760
|
fontWeight ? `font-weight: ${fontWeight};` : "",
|
|
@@ -1747,7 +1767,7 @@ function Button({ config, devMode }) {
|
|
|
1747
1767
|
: "",
|
|
1748
1768
|
direction ? `direction: ${direction};` : "",
|
|
1749
1769
|
opacity !== undefined ? `opacity: ${opacity};` : "",
|
|
1750
|
-
whiteSpace
|
|
1770
|
+
whiteSpace ? `white-space: ${whiteSpace};` : "",
|
|
1751
1771
|
]
|
|
1752
1772
|
.filter(Boolean)
|
|
1753
1773
|
.join(" ");
|
|
@@ -1762,33 +1782,43 @@ function Button({ config, devMode }) {
|
|
|
1762
1782
|
padding: 0,
|
|
1763
1783
|
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { align: align, style: {
|
|
1764
1784
|
padding: 0,
|
|
1765
|
-
}, children: jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style:
|
|
1785
|
+
}, children: jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1766
1786
|
// --- Start dev
|
|
1767
|
-
position: "relative",
|
|
1787
|
+
position: "relative",
|
|
1768
1788
|
// --- End dev
|
|
1769
|
-
width: width || "auto"
|
|
1789
|
+
width: width || "auto",
|
|
1790
|
+
...(maxWidth && { maxWidth: maxWidth }),
|
|
1791
|
+
borderCollapse: "collapse",
|
|
1770
1792
|
// base
|
|
1771
|
-
boxSizing: "border-box",
|
|
1793
|
+
boxSizing: "border-box",
|
|
1794
|
+
border: 0,
|
|
1795
|
+
margin: 0,
|
|
1796
|
+
padding: 0,
|
|
1797
|
+
}, onClick: devMode ? (e) => e.preventDefault() : undefined, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { dangerouslySetInnerHTML: {
|
|
1772
1798
|
__html: `
|
|
1773
|
-
${
|
|
1799
|
+
${useSimpleOutlookApproach ? simpleOutlookButton : vmlButton}
|
|
1774
1800
|
<!--[if !mso]><!-->
|
|
1775
1801
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
|
|
1776
1802
|
<tbody>
|
|
1777
1803
|
<tr>
|
|
1778
|
-
<td style="background-color: ${backgroundTdStyle.backgroundColor}
|
|
1779
|
-
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}
|
|
1804
|
+
<td style="${backgroundTdStyle.backgroundColor ? `background-color: ${backgroundTdStyle.backgroundColor};` : ""} ${backgroundTdStyle.borderRadius ? `border-radius: ${backgroundTdStyle.borderRadius};` : ""} width: ${backgroundTdStyle.width}; ${maxWidth ? `max-width: ${maxWidth};` : ""} ${borderRadius ? "overflow: hidden;" : ""}">
|
|
1805
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; ${borderRadius ? `border-radius: ${borderRadius};` : ""} width: 100%; ${borderStyleString}">
|
|
1780
1806
|
<tbody>
|
|
1781
1807
|
<tr>
|
|
1782
1808
|
<td style="padding: 0;">
|
|
1783
1809
|
${devMode
|
|
1784
|
-
? `<span style="${sharedTextStyles} display: block; text-align: ${textAlign}
|
|
1810
|
+
? `<span style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; ${wordBreak ? `word-break: ${wordBreak};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${padding ? `padding: ${padding};` : ""}">
|
|
1785
1811
|
${typeof children === "string" ? children : ""}
|
|
1786
1812
|
</span>`
|
|
1787
|
-
:
|
|
1788
|
-
|
|
1813
|
+
: href
|
|
1814
|
+
? `<a href="${href}" target="${target}" rel="noopener noreferrer" style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; ${wordBreak ? `word-break: ${wordBreak};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${padding ? `padding: ${padding};` : ""}">
|
|
1815
|
+
<span>
|
|
1816
|
+
${typeof children === "string" ? children : ""}
|
|
1817
|
+
</span>
|
|
1818
|
+
</a>`
|
|
1819
|
+
: `<span style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; ${wordBreak ? `word-break: ${wordBreak};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${padding ? `padding: ${padding};` : ""}">
|
|
1789
1820
|
${typeof children === "string" ? children : ""}
|
|
1790
|
-
</span
|
|
1791
|
-
</a>`}
|
|
1821
|
+
</span>`}
|
|
1792
1822
|
</td>
|
|
1793
1823
|
</tr>
|
|
1794
1824
|
</tbody>
|
|
@@ -1865,14 +1895,31 @@ function Column({ children, config, devNode }) {
|
|
|
1865
1895
|
};
|
|
1866
1896
|
// 2. Outer TD style: Background and Border Radius (no border here).
|
|
1867
1897
|
// height is set so the TD occupies the full declared height.
|
|
1868
|
-
const outerTdStyle =
|
|
1898
|
+
const outerTdStyle = {
|
|
1899
|
+
width: config.width,
|
|
1900
|
+
height: config.height,
|
|
1901
|
+
backgroundColor: config.backgroundColor,
|
|
1902
|
+
borderRadius: config.borderRadius,
|
|
1869
1903
|
// Background Image styles
|
|
1870
1904
|
backgroundImage: config.backgroundImage
|
|
1871
1905
|
? `url(${config.backgroundImage.src})`
|
|
1872
|
-
: undefined,
|
|
1906
|
+
: undefined,
|
|
1907
|
+
backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat,
|
|
1908
|
+
backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size,
|
|
1909
|
+
backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
|
|
1910
|
+
// Overflow hidden to clip background to border-radius
|
|
1911
|
+
...(config.borderRadius && { overflow: "hidden" }),
|
|
1912
|
+
};
|
|
1873
1913
|
// 2b. Inner table style: Border and Border Radius.
|
|
1874
1914
|
// height: 100% so it stretches to fill the outer TD's declared height.
|
|
1875
|
-
const innerTableStyle =
|
|
1915
|
+
const innerTableStyle = {
|
|
1916
|
+
width: "100%",
|
|
1917
|
+
height: "100%", // fill the outer TD rather than re-declaring the pixel value
|
|
1918
|
+
borderCollapse: "separate",
|
|
1919
|
+
borderSpacing: 0,
|
|
1920
|
+
borderRadius: config.borderRadius,
|
|
1921
|
+
...getBorderStyle$5(config.border),
|
|
1922
|
+
};
|
|
1876
1923
|
// 3. Inner TD style: Padding and Vertical Alignment only.
|
|
1877
1924
|
// *** No height here. ***
|
|
1878
1925
|
// The outer TD/table owns the height; padding is purely inner spacing,
|
|
@@ -1904,7 +1951,10 @@ function Column({ children, config, devNode }) {
|
|
|
1904
1951
|
: "top", align: config.alignItems
|
|
1905
1952
|
? alignMap$2[config.alignItems]
|
|
1906
1953
|
: "left", children: child }) }), index < numChildren - 1 && (jsx("tr", { children: jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) }) }) }) }));
|
|
1907
|
-
return (jsxs("table",
|
|
1954
|
+
return (jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1955
|
+
position: "relative",
|
|
1956
|
+
...outerTableStyle,
|
|
1957
|
+
}, ...(config.height && { height: config.height }), children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: outerTdStyle, ...(config.width && { width: config.width }), ...(config.height && { height: config.height }), children: renderContent() }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
1908
1958
|
}
|
|
1909
1959
|
var Column_default = memo(Column, arePropsEqual);
|
|
1910
1960
|
|
|
@@ -2009,11 +2059,27 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2009
2059
|
borderCollapse: "collapse",
|
|
2010
2060
|
};
|
|
2011
2061
|
// 1. Background TD Style - Background color, border radius, background image
|
|
2012
|
-
const backgroundTdStyle =
|
|
2062
|
+
const backgroundTdStyle = {
|
|
2063
|
+
backgroundColor: config.backgroundColor,
|
|
2064
|
+
borderRadius: config.borderRadius,
|
|
2065
|
+
maxWidth: widthType === "fixed" ? config.width || "600px" : undefined,
|
|
2066
|
+
backgroundImage: config.backgroundImage
|
|
2013
2067
|
? `url(${config.backgroundImage.src})`
|
|
2014
|
-
: undefined,
|
|
2068
|
+
: undefined,
|
|
2069
|
+
backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat,
|
|
2070
|
+
backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size,
|
|
2071
|
+
backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
|
|
2072
|
+
// Overflow hidden to clip background to border-radius
|
|
2073
|
+
...(config.borderRadius && { overflow: "hidden" }),
|
|
2074
|
+
};
|
|
2015
2075
|
// 2. Border Table Style - Border and border radius
|
|
2016
|
-
const borderTableStyle =
|
|
2076
|
+
const borderTableStyle = {
|
|
2077
|
+
width: "100%",
|
|
2078
|
+
borderCollapse: "separate",
|
|
2079
|
+
borderSpacing: 0,
|
|
2080
|
+
borderRadius: config.borderRadius,
|
|
2081
|
+
...getBorderStyle$4(config.border),
|
|
2082
|
+
};
|
|
2017
2083
|
// 3. Padding TD Style
|
|
2018
2084
|
const innerTdStyle = {
|
|
2019
2085
|
padding: config.padding,
|
|
@@ -2053,7 +2119,10 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2053
2119
|
}
|
|
2054
2120
|
return (jsx("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: child }, `child-${index}`));
|
|
2055
2121
|
});
|
|
2056
|
-
return (jsx("table", { "aria-label": `Container | Table Outer`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style:
|
|
2122
|
+
return (jsx("table", { "aria-label": `Container | Table Outer`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: {
|
|
2123
|
+
position: "relative",
|
|
2124
|
+
...outerTableStyle,
|
|
2125
|
+
}, children: jsx("tbody", { children: jsx("tr", { children: jsxs("td", { align: justifyAlign, children: [jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedWrapper } }), jsxs("table", { className: [
|
|
2057
2126
|
widthType === "fixed" ? "container-fixed-width" : undefined,
|
|
2058
2127
|
devMode ? "main-wrapper relative" : undefined,
|
|
2059
2128
|
]
|
|
@@ -2068,40 +2137,48 @@ var Container_default = memo(Container, arePropsEqual);
|
|
|
2068
2137
|
|
|
2069
2138
|
function Divider({ config, devNode }) {
|
|
2070
2139
|
const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", hideOnMobile, } = config;
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
//
|
|
2079
|
-
const
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
backgroundColor: color,
|
|
2083
|
-
borderCollapse: "collapse",
|
|
2084
|
-
border: "0",
|
|
2085
|
-
// ✅ FIX 1: Use string literal indexing for MSO properties
|
|
2086
|
-
// ["mso-table-lspace" as string]: "0pt",
|
|
2087
|
-
["msoTableLspace"]: "0pt",
|
|
2088
|
-
// ["mso-table-rspace" as string]: "0pt",
|
|
2089
|
-
["msoTableRspace"]: "0pt",
|
|
2090
|
-
};
|
|
2091
|
-
// Parse height for the HTML attribute
|
|
2092
|
-
const dividerHeightAttribute = parseInt(height, 10) || 1;
|
|
2093
|
-
return (jsxs("table", { "aria-label": "Divider Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2094
|
-
// --- Start dev
|
|
2095
|
-
position: "relative",
|
|
2096
|
-
// --- End dev
|
|
2140
|
+
const heightPx = parseInt(height, 10) || 1;
|
|
2141
|
+
// Parse margin into paddingTop / paddingBottom for the outer TD.
|
|
2142
|
+
// Outlook ignores shorthand "20px 0" on TDs — must be explicit.
|
|
2143
|
+
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw] = margin.trim().split(/\s+/);
|
|
2144
|
+
const marginTop = marginTopRaw;
|
|
2145
|
+
const marginBottom = marginBottomRaw !== null && marginBottomRaw !== void 0 ? marginBottomRaw : marginTopRaw; // "20px 0" → top=20px, bottom=20px
|
|
2146
|
+
// Outlook requires align on the outer TD to correctly position
|
|
2147
|
+
// a fixed-width inner table (e.g. width="300px").
|
|
2148
|
+
const alignAttr = align === "left" ? "left" : align === "right" ? "right" : "center";
|
|
2149
|
+
return (jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2150
|
+
position: "relative", // dev overlay anchor
|
|
2097
2151
|
width: "100%",
|
|
2098
2152
|
borderCollapse: "collapse",
|
|
2099
|
-
|
|
2153
|
+
border: "0",
|
|
2154
|
+
}, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { align: alignAttr, style: {
|
|
2155
|
+
paddingTop: marginTop,
|
|
2156
|
+
paddingBottom: marginBottom,
|
|
2157
|
+
paddingLeft: "0",
|
|
2158
|
+
paddingRight: "0",
|
|
2159
|
+
fontSize: "0",
|
|
2160
|
+
lineHeight: "0",
|
|
2161
|
+
}, children: jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: alignAttr, style: {
|
|
2162
|
+
width: width,
|
|
2163
|
+
borderCollapse: "collapse",
|
|
2164
|
+
border: "0",
|
|
2165
|
+
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { ...{ height: heightPx }, ref: (el) => {
|
|
2166
|
+
if (!el)
|
|
2167
|
+
return;
|
|
2168
|
+
el.setAttribute("style", `height:${height};` +
|
|
2169
|
+
`line-height:${height};` +
|
|
2170
|
+
`font-size:0;` +
|
|
2171
|
+
`padding:0;` +
|
|
2172
|
+
`background-color:${color};` +
|
|
2173
|
+
`mso-line-height-rule:exactly;`);
|
|
2174
|
+
}, style: {
|
|
2175
|
+
// Fallback for non-Outlook clients (React-rendered style object).
|
|
2100
2176
|
height: height,
|
|
2177
|
+
lineHeight: height,
|
|
2101
2178
|
fontSize: "0",
|
|
2102
|
-
lineHeight: "0",
|
|
2103
2179
|
padding: "0",
|
|
2104
|
-
|
|
2180
|
+
backgroundColor: color,
|
|
2181
|
+
} }) }) }) }) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2105
2182
|
}
|
|
2106
2183
|
var Divider_default = memo(Divider, arePropsEqual);
|
|
2107
2184
|
|
|
@@ -2279,7 +2356,7 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2279
2356
|
}
|
|
2280
2357
|
h1, h2, h3, h4, h5, h6 { margin: 0; padding: 0; font-weight: inherit; }
|
|
2281
2358
|
`;
|
|
2282
|
-
return (jsxs("head", { children: [jsx("meta", { httpEquiv: "Content-Type", content: "text/html; charset=utf-8" }), jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), jsx("meta", { httpEquiv: "X-UA-Compatible", content: "IE=edge" }), jsx("title", { children: title }), fonts.flatMap((resolved) => resolved.fontProps.map((props, i) => (jsx(Font,
|
|
2359
|
+
return (jsxs("head", { children: [jsx("meta", { httpEquiv: "Content-Type", content: "text/html; charset=utf-8" }), jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), jsx("meta", { httpEquiv: "X-UA-Compatible", content: "IE=edge" }), jsx("title", { children: title }), fonts.flatMap((resolved) => resolved.fontProps.map((props, i) => (jsx(Font, { ...props }, `${resolved.family}-${props.fontWeight}-${props.fontStyle}-${i}`)))), children, jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: msoResetStyles } }), jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: globalStyles } })] }));
|
|
2283
2360
|
}
|
|
2284
2361
|
|
|
2285
2362
|
function Heading({ config, devMode, children }) {
|
|
@@ -2346,6 +2423,27 @@ function Html({ children, backgroundColor = "#ffffff", }) {
|
|
|
2346
2423
|
);
|
|
2347
2424
|
}
|
|
2348
2425
|
|
|
2426
|
+
// Helper to build link href based on innerLink type
|
|
2427
|
+
function buildLinkHref$1(innerLink) {
|
|
2428
|
+
if (!innerLink || innerLink.type === "none")
|
|
2429
|
+
return null;
|
|
2430
|
+
switch (innerLink.type) {
|
|
2431
|
+
case "url":
|
|
2432
|
+
return innerLink.url || null;
|
|
2433
|
+
case "email":
|
|
2434
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
2435
|
+
case "phone":
|
|
2436
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
2437
|
+
case "anchor":
|
|
2438
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
2439
|
+
case "page_top":
|
|
2440
|
+
return "#top";
|
|
2441
|
+
case "page_bottom":
|
|
2442
|
+
return "#bottom";
|
|
2443
|
+
default:
|
|
2444
|
+
return null;
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2349
2447
|
function getBorderStyle$3(border) {
|
|
2350
2448
|
if (!border)
|
|
2351
2449
|
return {};
|
|
@@ -2387,8 +2485,11 @@ function getBorderStyleString$1(border) {
|
|
|
2387
2485
|
return styles.join(" ");
|
|
2388
2486
|
}
|
|
2389
2487
|
function Image({ config, devNode, devMode }) {
|
|
2390
|
-
var _a;
|
|
2391
|
-
const { src, alt,
|
|
2488
|
+
var _a, _b;
|
|
2489
|
+
const { src, alt, innerLink, mobile } = config;
|
|
2490
|
+
// Resolve href and target from innerLink
|
|
2491
|
+
const href = buildLinkHref$1(innerLink);
|
|
2492
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2392
2493
|
const seed = src + (alt || "");
|
|
2393
2494
|
const instanceId = seed
|
|
2394
2495
|
.split("")
|
|
@@ -2403,38 +2504,89 @@ function Image({ config, devNode, devMode }) {
|
|
|
2403
2504
|
// Determine the table's "initial" width.
|
|
2404
2505
|
// If it's 300px, the table should be 300px, not 100%.
|
|
2405
2506
|
const tableWidth = isPercent ? desktopWidth : `${widthAttr}px`;
|
|
2406
|
-
//
|
|
2507
|
+
// When width is a percentage, Outlook ignores CSS and renders the image at
|
|
2508
|
+
// its intrinsic pixel size. Setting a concrete `width` HTML attribute gives
|
|
2509
|
+
// Outlook a value to constrain against while modern clients continue to use
|
|
2510
|
+
// the CSS `width: 100%` for fluid rendering.
|
|
2511
|
+
//
|
|
2512
|
+
// If `maxWidth` is a pixel value (e.g. "600px"), we extract the number and
|
|
2513
|
+
// use it as the HTML `width` attribute so Outlook enforces that cap.
|
|
2514
|
+
// Other clients ignore the attribute and rely on CSS styles instead.
|
|
2515
|
+
// If `maxWidth` is not set or is not a pixel value (e.g. "100%"), we fall
|
|
2516
|
+
// back to the original behaviour (numeric string for px widths, undefined
|
|
2517
|
+
// for % widths).
|
|
2518
|
+
const maxWidthPx = ((_b = config.maxWidth) === null || _b === void 0 ? void 0 : _b.endsWith("px"))
|
|
2519
|
+
? parseInt(config.maxWidth, 10)
|
|
2520
|
+
: undefined;
|
|
2521
|
+
const imgWidthAttr = isPercent ? (maxWidthPx !== null && maxWidthPx !== void 0 ? maxWidthPx : undefined) : widthAttr;
|
|
2522
|
+
// 2. Mobile Overrides — only emit CSS properties that are explicitly set,
|
|
2523
|
+
// so unspecified properties are left untouched (no forced defaults).
|
|
2407
2524
|
let mobileCss = "";
|
|
2408
2525
|
if (mobile) {
|
|
2526
|
+
// .wrap-${imgClass} rules
|
|
2527
|
+
const wrapRules = [
|
|
2528
|
+
// Always reset min-width so the px lock from desktop can be overridden
|
|
2529
|
+
"min-width: 0 !important;",
|
|
2530
|
+
];
|
|
2531
|
+
if (mobile.width !== undefined)
|
|
2532
|
+
wrapRules.push(`width: ${mobile.width} !important;`);
|
|
2533
|
+
if (mobile.maxWidth !== undefined)
|
|
2534
|
+
wrapRules.push(`max-width: ${mobile.maxWidth} !important;`);
|
|
2535
|
+
// .td-${imgClass} rules
|
|
2536
|
+
const tdRules = [];
|
|
2537
|
+
if (mobile.padding !== undefined)
|
|
2538
|
+
tdRules.push(`padding: ${mobile.padding} !important;`);
|
|
2539
|
+
if (mobile.backgroundColor !== undefined)
|
|
2540
|
+
tdRules.push(`background-color: ${mobile.backgroundColor} !important;`);
|
|
2541
|
+
// .${imgClass} rules
|
|
2542
|
+
const imgRules = [];
|
|
2543
|
+
if (mobile.width !== undefined)
|
|
2544
|
+
imgRules.push(`width: ${mobile.width} !important;`);
|
|
2545
|
+
if (mobile.height !== undefined)
|
|
2546
|
+
imgRules.push(`height: ${mobile.height} !important;`);
|
|
2547
|
+
if (mobile.maxWidth !== undefined)
|
|
2548
|
+
imgRules.push(`max-width: ${mobile.maxWidth} !important;`);
|
|
2549
|
+
if (mobile.maxHeight !== undefined)
|
|
2550
|
+
imgRules.push(`max-height: ${mobile.maxHeight} !important;`);
|
|
2551
|
+
if (mobile.borderRadius !== undefined)
|
|
2552
|
+
imgRules.push(`border-radius: ${mobile.borderRadius} !important;`);
|
|
2553
|
+
if (mobile.hidden !== undefined)
|
|
2554
|
+
imgRules.push(`display: ${mobile.hidden ? "none" : "block"} !important;`);
|
|
2555
|
+
if (mobile.objectFit !== undefined)
|
|
2556
|
+
imgRules.push(`object-fit: ${mobile.objectFit} !important;`);
|
|
2557
|
+
if (mobile.objectPosition !== undefined)
|
|
2558
|
+
imgRules.push(`object-position: ${mobile.objectPosition} !important;`);
|
|
2559
|
+
if (mobile.border !== undefined)
|
|
2560
|
+
imgRules.push(getBorderStyleString$1(mobile.border));
|
|
2409
2561
|
mobileCss = `
|
|
2410
2562
|
@media screen and (max-width: 768px) {
|
|
2411
2563
|
.wrap-${imgClass} {
|
|
2412
2564
|
/* This breaks the px lock from desktop and makes it fluid */
|
|
2413
|
-
|
|
2414
|
-
max-width: ${mobile.maxWidth || "100%"} !important;
|
|
2415
|
-
min-width: 0 !important;
|
|
2565
|
+
${wrapRules.join("\n ")}
|
|
2416
2566
|
}
|
|
2417
2567
|
.td-${imgClass} {
|
|
2418
|
-
|
|
2419
|
-
background-color: ${mobile.backgroundColor || "transparent"} !important;
|
|
2420
|
-
width: 100% !important;
|
|
2568
|
+
${tdRules.join("\n ")}
|
|
2421
2569
|
}
|
|
2422
2570
|
.${imgClass} {
|
|
2423
|
-
|
|
2424
|
-
height: ${mobile.height || "auto"} !important;
|
|
2425
|
-
max-width: ${mobile.maxWidth || "100%"} !important;
|
|
2426
|
-
max-height: ${mobile.maxHeight || "none"} !important;
|
|
2427
|
-
border-radius: ${mobile.borderRadius || "0"} !important;
|
|
2428
|
-
display: ${mobile.hidden ? "none" : "block"} !important;
|
|
2429
|
-
object-fit: ${mobile.objectFit || "fill"} !important;
|
|
2430
|
-
object-position: ${mobile.objectPosition || "center"} !important;
|
|
2431
|
-
${getBorderStyleString$1(mobile.border)}
|
|
2571
|
+
${imgRules.join("\n ")}
|
|
2432
2572
|
}
|
|
2433
2573
|
}
|
|
2434
2574
|
`;
|
|
2435
2575
|
}
|
|
2436
|
-
const imgStyle =
|
|
2437
|
-
|
|
2576
|
+
const imgStyle = {
|
|
2577
|
+
display: "block",
|
|
2578
|
+
width: isPercent ? "100%" : desktopWidth,
|
|
2579
|
+
height: config.height || "auto",
|
|
2580
|
+
maxWidth: config.maxWidth || "100%",
|
|
2581
|
+
maxHeight: config.maxHeight || "none",
|
|
2582
|
+
borderRadius: config.borderRadius || "0",
|
|
2583
|
+
...getBorderStyle$3(config.border),
|
|
2584
|
+
outline: "none",
|
|
2585
|
+
textDecoration: "none",
|
|
2586
|
+
objectFit: config.objectFit,
|
|
2587
|
+
objectPosition: config.objectPosition,
|
|
2588
|
+
};
|
|
2589
|
+
const imageElement = (jsx("img", { src: src, alt: alt, width: imgWidthAttr, height: heightAttr !== "auto" ? heightAttr : undefined, className: imgClass, style: imgStyle, draggable: !devMode }));
|
|
2438
2590
|
return (jsxs(Fragment$1, { children: [mobile && jsx("style", { dangerouslySetInnerHTML: { __html: mobileCss } }), jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, className: `wrap-${imgClass}`, align: "center" // Ensures a 300px image stays centered in its parent
|
|
2439
2591
|
, style: {
|
|
2440
2592
|
width: tableWidth, // Fixed px here prevents the 100% "ghost space"
|
|
@@ -2447,7 +2599,9 @@ function Image({ config, devNode, devMode }) {
|
|
|
2447
2599
|
fontSize: "0",
|
|
2448
2600
|
lineHeight: "0",
|
|
2449
2601
|
width: tableWidth, // Lock the cell as well
|
|
2450
|
-
}, children: href && !devMode ? (jsx("a", { href: href, target: target,
|
|
2602
|
+
}, children: href && !devMode ? (jsx("a", { href: href, target: target, ...(target === "_blank"
|
|
2603
|
+
? { rel: "noopener noreferrer" }
|
|
2604
|
+
: {}), style: { display: "block", width: "100%" }, children: imageElement })) : (imageElement) }) }) }), devMode && !!devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] })] }));
|
|
2451
2605
|
}
|
|
2452
2606
|
var Image_default = memo(Image, arePropsEqual);
|
|
2453
2607
|
|
|
@@ -2521,13 +2675,30 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2521
2675
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2522
2676
|
const numChildren = childrenArray.length;
|
|
2523
2677
|
const href = getHrefFromInnerLink(config.innerLink);
|
|
2524
|
-
const target = (_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target;
|
|
2678
|
+
const target = ((_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target) || "_blank";
|
|
2525
2679
|
// 1. Outer TD: Background, Border Radius, Width, Height.
|
|
2526
|
-
const backgroundTdStyle =
|
|
2680
|
+
const backgroundTdStyle = {
|
|
2681
|
+
backgroundColor: config.backgroundColor,
|
|
2682
|
+
borderRadius: config.borderRadius,
|
|
2683
|
+
width: config.width || "100%",
|
|
2684
|
+
height: config.height,
|
|
2685
|
+
backgroundImage: config.backgroundImage
|
|
2527
2686
|
? `url(${config.backgroundImage.src})`
|
|
2528
|
-
: undefined,
|
|
2687
|
+
: undefined,
|
|
2688
|
+
backgroundRepeat: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.repeat,
|
|
2689
|
+
backgroundSize: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size,
|
|
2690
|
+
backgroundPosition: (_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position,
|
|
2691
|
+
...(config.borderRadius && { overflow: "hidden" }),
|
|
2692
|
+
};
|
|
2529
2693
|
// 2. Inner Table: Border and Border Radius.
|
|
2530
|
-
const borderTableStyle =
|
|
2694
|
+
const borderTableStyle = {
|
|
2695
|
+
width: "100%",
|
|
2696
|
+
height: "100%",
|
|
2697
|
+
borderCollapse: "separate",
|
|
2698
|
+
borderSpacing: 0,
|
|
2699
|
+
borderRadius: config.borderRadius,
|
|
2700
|
+
...getBorderStyle$2(config.border),
|
|
2701
|
+
};
|
|
2531
2702
|
// 3. Padding TD.
|
|
2532
2703
|
const paddingTdStyle = {
|
|
2533
2704
|
padding: config.padding,
|
|
@@ -2545,7 +2716,13 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2545
2716
|
// Content table fills available space, giving Outlook Classic a hard
|
|
2546
2717
|
// boundary so text children get a constrained box and line wrapping
|
|
2547
2718
|
// triggers correctly. Use for rows containing text + image layouts.
|
|
2548
|
-
const contentTableStyle =
|
|
2719
|
+
const contentTableStyle = {
|
|
2720
|
+
width: config.fillWidth ? "100%" : "auto",
|
|
2721
|
+
height: "100%",
|
|
2722
|
+
borderCollapse: "collapse",
|
|
2723
|
+
minWidth: "1px",
|
|
2724
|
+
...(!config.fillWidth && { maxWidth: config.width || "100%" }),
|
|
2725
|
+
};
|
|
2549
2726
|
// 5. Gap TD.
|
|
2550
2727
|
const gapTdStyle = {
|
|
2551
2728
|
width: config.gap || "0",
|
|
@@ -2556,28 +2733,28 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2556
2733
|
? justifyMap$1[config.justifyContent]
|
|
2557
2734
|
: "left";
|
|
2558
2735
|
const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
|
|
2559
|
-
const content = (jsxs("table",
|
|
2736
|
+
const content = (jsxs("table", { "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2560
2737
|
position: "relative",
|
|
2561
2738
|
width: config.width || "100%",
|
|
2562
2739
|
height: config.height,
|
|
2563
2740
|
borderCollapse: "collapse",
|
|
2564
|
-
}
|
|
2741
|
+
}, ...(config.height && { height: config.height }), children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: backgroundTdStyle, ...(config.height && { height: config.height }), children: jsx("table", { "aria-label": "Row Border Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: borderTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: paddingTdStyle, children: jsx("table", { "aria-label": "Row Justification Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2565
2742
|
width: "100%",
|
|
2566
2743
|
height: "100%",
|
|
2567
2744
|
borderCollapse: "collapse",
|
|
2568
|
-
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { align: tdAlign, width: "100%", style: { width: "100%" }, children: jsx("table",
|
|
2745
|
+
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { align: tdAlign, width: "100%", style: { width: "100%" }, children: jsx("table", { "aria-label": "Row Content", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: contentTableStyle, ...(config.height && { height: config.height }), className: "content-table row-content-table", "data-mobile-justify": (_e = config.mobile) === null || _e === void 0 ? void 0 : _e.justifyContent, "data-mobile-align": (_f = config.mobile) === null || _f === void 0 ? void 0 : _f.alignItems, "data-mobile-wrap": ((_g = config.mobile) === null || _g === void 0 ? void 0 : _g.wrap) ? "true" : undefined, "data-gap": config.gap, children: jsx("tbody", { children: jsx("tr", { className: "content-tr", children: childrenArray.map((child, index) => (jsxs(Fragment, { children: [jsx("td", { valign: tdValign, style: {
|
|
2569
2746
|
verticalAlign: tdValign,
|
|
2570
2747
|
textAlign: "left",
|
|
2571
2748
|
padding: "0",
|
|
2572
2749
|
margin: "0",
|
|
2573
2750
|
}, className: "child-cell", children: child }), index < numChildren - 1 &&
|
|
2574
|
-
config.gap && (jsx("td", { width: config.gap, style: gapTdStyle, className: "row-gap-td", children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) })
|
|
2751
|
+
config.gap && (jsx("td", { width: config.gap, style: gapTdStyle, className: "row-gap-td", children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) }) }) }) }) }) }) }) }) }) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2575
2752
|
if (href && !devMode) {
|
|
2576
|
-
return (jsx("a",
|
|
2753
|
+
return (jsx("a", { href: href, ...({ target }), style: {
|
|
2577
2754
|
textDecoration: "none",
|
|
2578
2755
|
color: "inherit",
|
|
2579
2756
|
display: "block",
|
|
2580
|
-
}, children: content }))
|
|
2757
|
+
}, children: content }));
|
|
2581
2758
|
}
|
|
2582
2759
|
return content;
|
|
2583
2760
|
}
|
|
@@ -2621,9 +2798,18 @@ function getBorderStyle$1(border) {
|
|
|
2621
2798
|
const Section = ({ config, children, devNode, }) => {
|
|
2622
2799
|
var _a, _b, _c;
|
|
2623
2800
|
const { sectionType, padding } = config;
|
|
2624
|
-
return (jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style:
|
|
2801
|
+
return (jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2802
|
+
position: "relative",
|
|
2803
|
+
width: "100%",
|
|
2804
|
+
backgroundColor: config.backgroundColor,
|
|
2805
|
+
...getBorderStyle$1(config.border),
|
|
2806
|
+
backgroundImage: config.backgroundImage
|
|
2625
2807
|
? `url(${config.backgroundImage.src})`
|
|
2626
|
-
: undefined,
|
|
2808
|
+
: undefined,
|
|
2809
|
+
backgroundRepeat: (_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.repeat,
|
|
2810
|
+
backgroundSize: (_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.size,
|
|
2811
|
+
backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
|
|
2812
|
+
}, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: {
|
|
2627
2813
|
padding: padding,
|
|
2628
2814
|
}, children: children }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsxs("td", { children: [jsxs("span", { style: {
|
|
2629
2815
|
backgroundColor: "black",
|
|
@@ -2664,11 +2850,14 @@ function Spacer({ config, devNode }) {
|
|
|
2664
2850
|
const spacerHeightAttribute = parseInt(height, 10) || 1;
|
|
2665
2851
|
return (
|
|
2666
2852
|
// Outer table ensures the spacer spans the full width of its container
|
|
2667
|
-
jsxs("table",
|
|
2853
|
+
jsxs("table", { "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2668
2854
|
// --- Start dev
|
|
2669
|
-
position: "relative"
|
|
2855
|
+
position: "relative",
|
|
2856
|
+
// --- End dev
|
|
2857
|
+
...spacerTableStyle,
|
|
2858
|
+
}, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: spacerTdStyle,
|
|
2670
2859
|
// Explicit height attribute
|
|
2671
|
-
height: spacerHeightAttribute, children: "\u00A0" }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }))
|
|
2860
|
+
height: spacerHeightAttribute, children: "\u00A0" }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2672
2861
|
}
|
|
2673
2862
|
var Spacer_default = memo(Spacer, arePropsEqual);
|
|
2674
2863
|
|
|
@@ -2807,7 +2996,7 @@ function buildIconifyUrl(config) {
|
|
|
2807
2996
|
const template = process.env.ICONIFY_API_IMAGE_URI ||
|
|
2808
2997
|
"https://iconify.pagenflow.com/api/image/{{height}}/{{color}}/{{rotate}}-{{rotate-orientation}}/{{icon-full-name}}.png";
|
|
2809
2998
|
return template
|
|
2810
|
-
.replace("{{height}}", String(numericHeight *
|
|
2999
|
+
.replace("{{height}}", String(numericHeight * 4))
|
|
2811
3000
|
.replace("{{color}}", cleanColor)
|
|
2812
3001
|
.replace("{{rotate}}", String(rotate))
|
|
2813
3002
|
.replace("{{rotate-orientation}}", rotateOrientation)
|
|
@@ -2841,7 +3030,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2841
3030
|
// Determine icon source
|
|
2842
3031
|
const iconSrc = buildIconifyUrl(config);
|
|
2843
3032
|
const href = buildLinkHref(innerLink);
|
|
2844
|
-
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "
|
|
3033
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2845
3034
|
const align = justifyMap[justifyContent];
|
|
2846
3035
|
// Get border styles
|
|
2847
3036
|
const borderStyle = getBorderStyle(border);
|
|
@@ -2884,7 +3073,13 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2884
3073
|
lineHeight: "0",
|
|
2885
3074
|
};
|
|
2886
3075
|
// 4. Inner Table Style: Apply border here with border-collapse: separate
|
|
2887
|
-
const innerTableStyle =
|
|
3076
|
+
const innerTableStyle = {
|
|
3077
|
+
width: "100%",
|
|
3078
|
+
borderCollapse: "separate",
|
|
3079
|
+
borderSpacing: 0,
|
|
3080
|
+
borderRadius: borderRadius,
|
|
3081
|
+
...borderStyle,
|
|
3082
|
+
};
|
|
2888
3083
|
// 5. Inner TD Style: Padding
|
|
2889
3084
|
const innerTdStyle = {
|
|
2890
3085
|
padding: padding,
|
|
@@ -2932,7 +3127,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2932
3127
|
// Icon image element
|
|
2933
3128
|
const iconElement = devMode && !!children ? (children) : iconSrc ? (jsx("img", { draggable: false, src: iconSrc, alt: "", style: imgStyle, width: widthNum, height: heightNum, border: 0 })) : (jsx(Fragment$1, {}));
|
|
2934
3129
|
// Wrap in link if href exists and not in dev mode
|
|
2935
|
-
const content = href && !devMode ? (jsx("a",
|
|
3130
|
+
const content = href && !devMode ? (jsx("a", { href: href, target: target, style: linkStyle, ...(target === "_blank" ? { rel: "noopener noreferrer" } : {}), children: iconElement })) : (iconElement);
|
|
2936
3131
|
// Build the HTML content with VML support (only when NOT in dev mode)
|
|
2937
3132
|
const useVML = !devMode && backgroundColor && numericBorderRadius > 0;
|
|
2938
3133
|
const htmlContent = useVML
|