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