@pagenflow/email 1.4.7 → 1.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Button.d.ts +3 -1
- package/dist/components/Column.d.ts +3 -1
- package/dist/components/Container.d.ts +4 -2
- package/dist/components/Divider.d.ts +3 -1
- package/dist/components/Heading.d.ts +6 -1
- package/dist/components/Icon.d.ts +4 -2
- package/dist/components/Image.d.ts +25 -2
- package/dist/components/Row.d.ts +20 -1
- package/dist/components/Section.d.ts +2 -0
- package/dist/components/Spacer.d.ts +6 -1
- package/dist/components/Text.d.ts +6 -1
- package/dist/components/utils/bindingAttribute.d.ts +38 -0
- package/dist/components/utils/injectParagraphReset.d.ts +1 -0
- package/dist/components/utils/isGapZero.d.ts +1 -0
- package/dist/components/utils/linearizeStyle.d.ts +10 -0
- package/dist/index.cjs.js +346 -138
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +346 -138
- package/dist/index.esm.js.map +1 -1
- package/dist/types/DataBindings.d.ts +87 -0
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1531,6 +1531,57 @@ function arePropsEqual(prevProps, nextProps) {
|
|
|
1531
1531
|
return isEqual(prevProps, nextProps);
|
|
1532
1532
|
}
|
|
1533
1533
|
|
|
1534
|
+
/**
|
|
1535
|
+
* bindingAttribute.ts
|
|
1536
|
+
* -------------------
|
|
1537
|
+
* Serialises DataBindings into discrete HTML attributes:
|
|
1538
|
+
*
|
|
1539
|
+
* data-bind-if → visible condition → stamped on the root element
|
|
1540
|
+
* data-bind-list → repeater (dataList + itemAlias) → stamped on the
|
|
1541
|
+
* direct parent of the children loop, NOT the root
|
|
1542
|
+
* data-bind → propertyMap → stamped on the root element
|
|
1543
|
+
*
|
|
1544
|
+
* Keeping the three concerns in separate attributes lets the post-processor
|
|
1545
|
+
* handle them independently without ambiguity.
|
|
1546
|
+
*/
|
|
1547
|
+
// ─── Root element props (visible + propertyMap) ───────────────────────────────
|
|
1548
|
+
/**
|
|
1549
|
+
* Props to spread onto the component's root element.
|
|
1550
|
+
* Carries `data-bind-if` and/or `data-bind` (propertyMap).
|
|
1551
|
+
*/
|
|
1552
|
+
function rootBindingProps(bindings) {
|
|
1553
|
+
if (!bindings)
|
|
1554
|
+
return {};
|
|
1555
|
+
const props = {};
|
|
1556
|
+
if (bindings.visible) {
|
|
1557
|
+
props['data-bind-if'] = bindings.visible;
|
|
1558
|
+
}
|
|
1559
|
+
if (bindings.propertyMap && Object.keys(bindings.propertyMap).length) {
|
|
1560
|
+
props['data-bind'] = JSON.stringify({ propertyMap: bindings.propertyMap });
|
|
1561
|
+
}
|
|
1562
|
+
return props;
|
|
1563
|
+
}
|
|
1564
|
+
// ─── List wrapper props (dataList + itemAlias) ────────────────────────────────
|
|
1565
|
+
/**
|
|
1566
|
+
* Props to spread onto the *direct parent* of the children loop.
|
|
1567
|
+
* Carries `data-bind-list` only when a repeater is defined.
|
|
1568
|
+
*
|
|
1569
|
+
* Usage inside a component:
|
|
1570
|
+
* <tbody {...listBindingProps(bindings)}>
|
|
1571
|
+
* {children}
|
|
1572
|
+
* </tbody>
|
|
1573
|
+
*/
|
|
1574
|
+
function listBindingProps(bindings) {
|
|
1575
|
+
if (!(bindings === null || bindings === void 0 ? void 0 : bindings.dataList))
|
|
1576
|
+
return {};
|
|
1577
|
+
return {
|
|
1578
|
+
'data-bind-list': JSON.stringify({
|
|
1579
|
+
dataList: bindings.dataList,
|
|
1580
|
+
...(bindings.itemAlias && { itemAlias: bindings.itemAlias }),
|
|
1581
|
+
}),
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1534
1585
|
// Map alignment to HTML 'align' attribute
|
|
1535
1586
|
const justifyMap$3 = {
|
|
1536
1587
|
start: "left",
|
|
@@ -1538,7 +1589,7 @@ const justifyMap$3 = {
|
|
|
1538
1589
|
end: "right",
|
|
1539
1590
|
};
|
|
1540
1591
|
// Helper to build link href based on innerLink type (mirrors Icon component)
|
|
1541
|
-
function buildLinkHref$
|
|
1592
|
+
function buildLinkHref$4(innerLink) {
|
|
1542
1593
|
if (!innerLink || innerLink.type === "none")
|
|
1543
1594
|
return null;
|
|
1544
1595
|
switch (innerLink.type) {
|
|
@@ -1592,10 +1643,10 @@ function getBorderStyleString$2(border) {
|
|
|
1592
1643
|
}
|
|
1593
1644
|
return styles.join(" ");
|
|
1594
1645
|
}
|
|
1595
|
-
function Button({ config, devMode }) {
|
|
1646
|
+
function Button({ config, devMode, bindings }) {
|
|
1596
1647
|
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
1648
|
// Resolve href from innerLink
|
|
1598
|
-
const href = buildLinkHref$
|
|
1649
|
+
const href = buildLinkHref$4(innerLink);
|
|
1599
1650
|
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
1600
1651
|
// Sanitize fontFamily early so safeFontFamily is available for all paths below.
|
|
1601
1652
|
const safeFontFamily = fontFamily
|
|
@@ -1679,7 +1730,7 @@ function Button({ config, devMode }) {
|
|
|
1679
1730
|
.join(" ");
|
|
1680
1731
|
return (
|
|
1681
1732
|
// Wrapper table for alignment - maintains proper positioning for hover indicators
|
|
1682
|
-
jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1733
|
+
jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
1683
1734
|
width: "100%",
|
|
1684
1735
|
borderCollapse: "collapse",
|
|
1685
1736
|
boxSizing: "border-box",
|
|
@@ -1739,6 +1790,15 @@ function Button({ config, devMode }) {
|
|
|
1739
1790
|
}
|
|
1740
1791
|
var Button_default = memo(Button, arePropsEqual);
|
|
1741
1792
|
|
|
1793
|
+
function isGapZero(gap) {
|
|
1794
|
+
if (!gap)
|
|
1795
|
+
return true;
|
|
1796
|
+
// Remove whitespace and convert to lowercase
|
|
1797
|
+
const trimmedGap = gap.trim().toLowerCase();
|
|
1798
|
+
// Check for exact zero matches (0, 0px, 0%, 0em, 0rem, etc.)
|
|
1799
|
+
return /^0(px|%|em|rem|ex|ch|vw|vh|vmin|vmax)?$/.test(trimmedGap);
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1742
1802
|
// Helper for vertical alignment
|
|
1743
1803
|
const vAlignMap = {
|
|
1744
1804
|
start: "top",
|
|
@@ -1787,7 +1847,7 @@ function getBorderStyle$5(border) {
|
|
|
1787
1847
|
}
|
|
1788
1848
|
return style;
|
|
1789
1849
|
}
|
|
1790
|
-
function Column({ children, config, devNode }) {
|
|
1850
|
+
function Column({ children, config, devNode, bindings }) {
|
|
1791
1851
|
var _a, _b, _c;
|
|
1792
1852
|
// Process children array for gap support
|
|
1793
1853
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
@@ -1839,6 +1899,7 @@ function Column({ children, config, devNode }) {
|
|
|
1839
1899
|
// treat it as content-box height and add padding on top, causing the
|
|
1840
1900
|
// total to exceed the declared height in preview mode.
|
|
1841
1901
|
verticalAlign: config.alignItems ? alignMap$2[config.alignItems] : "top",
|
|
1902
|
+
background: "transparent",
|
|
1842
1903
|
};
|
|
1843
1904
|
// 4. Gap spacer style (used between children)
|
|
1844
1905
|
const gapSpacerStyle = {
|
|
@@ -1846,6 +1907,7 @@ function Column({ children, config, devNode }) {
|
|
|
1846
1907
|
lineHeight: "1px",
|
|
1847
1908
|
fontSize: "1px",
|
|
1848
1909
|
width: "100%",
|
|
1910
|
+
background: "transparent",
|
|
1849
1911
|
};
|
|
1850
1912
|
// 5. maxWidth constraining table style (modern clients).
|
|
1851
1913
|
// The `width` HTML attribute on this table is what Outlook Classic
|
|
@@ -1860,10 +1922,10 @@ function Column({ children, config, devNode }) {
|
|
|
1860
1922
|
borderCollapse: "collapse",
|
|
1861
1923
|
};
|
|
1862
1924
|
// Main content rendering
|
|
1863
|
-
const renderContent = () => (jsx("table", { "aria-label": "Column Padding", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: innerTdStyle, valign: config.justifyContent ? vAlignMap[config.justifyContent] : "top", align: config.alignItems ? alignMap$2[config.alignItems] : "left",
|
|
1925
|
+
const renderContent = () => (jsx("table", { "aria-label": "Column Padding", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: innerTdStyle, valign: config.justifyContent ? vAlignMap[config.justifyContent] : "top", align: config.alignItems ? alignMap$2[config.alignItems] : "left", ...(numChildren > 1 ? {} : listBindingProps(bindings)), children: numChildren > 1 ? (jsx("table", { "aria-label": "Column Gap Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1864
1926
|
width: "100%",
|
|
1865
1927
|
borderCollapse: "collapse",
|
|
1866
|
-
}, children: jsx("tbody", { children: childrenArray.map((child, index) => (jsxs(Fragment, { children: [jsx("tr", { children: jsx("td", { style: {
|
|
1928
|
+
}, children: jsx("tbody", { ...listBindingProps(bindings), children: childrenArray.map((child, index) => (jsxs(Fragment, { children: [jsx("tr", { children: jsx("td", { style: {
|
|
1867
1929
|
verticalAlign: config.alignItems
|
|
1868
1930
|
? alignMap$2[config.alignItems]
|
|
1869
1931
|
: "top",
|
|
@@ -1871,8 +1933,8 @@ function Column({ children, config, devNode }) {
|
|
|
1871
1933
|
? vAlignMap[config.justifyContent]
|
|
1872
1934
|
: "top", align: config.alignItems
|
|
1873
1935
|
? alignMap$2[config.alignItems]
|
|
1874
|
-
: "left", children: child }) }), index < numChildren - 1 && (jsx("tr", { children: jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) }) }) }) }));
|
|
1875
|
-
return (jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1936
|
+
: "left", children: child }) }), index < numChildren - 1 && !isGapZero(config.gap) && (jsx("tr", { children: jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) }) }) }) }));
|
|
1937
|
+
return (jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
1876
1938
|
position: "relative",
|
|
1877
1939
|
...outerTableStyle,
|
|
1878
1940
|
}, ...(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: config.maxWidth ? (
|
|
@@ -1941,7 +2003,7 @@ function getBorderStyle$4(border) {
|
|
|
1941
2003
|
}
|
|
1942
2004
|
return style;
|
|
1943
2005
|
}
|
|
1944
|
-
function Container({ children, config, devMode, devNode }) {
|
|
2006
|
+
function Container({ children, config, bindings, devMode, devNode, }) {
|
|
1945
2007
|
var _a, _b, _c;
|
|
1946
2008
|
const { widthType, childrenConstraints } = config;
|
|
1947
2009
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
@@ -1959,7 +2021,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
1959
2021
|
return 0;
|
|
1960
2022
|
})();
|
|
1961
2023
|
const getChildWidths = (() => {
|
|
1962
|
-
const { widthDistributionType } = childrenConstraints;
|
|
2024
|
+
const { widthDistributionType } = childrenConstraints !== null && childrenConstraints !== void 0 ? childrenConstraints : {};
|
|
1963
2025
|
const totalGapSpace = gapWidthPx * (numChildren > 1 ? numChildren - 1 : 0);
|
|
1964
2026
|
const remainingContentSpace = containerWidthPx - totalGapSpace;
|
|
1965
2027
|
switch (widthDistributionType) {
|
|
@@ -2033,6 +2095,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2033
2095
|
width: config.gap || "0",
|
|
2034
2096
|
lineHeight: "1px",
|
|
2035
2097
|
fontSize: "1px",
|
|
2098
|
+
background: "transparent",
|
|
2036
2099
|
};
|
|
2037
2100
|
const justifyAlign = config.justifyContent
|
|
2038
2101
|
? justifyMap$2[config.justifyContent]
|
|
@@ -2048,19 +2111,20 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2048
2111
|
textAlign: "left",
|
|
2049
2112
|
};
|
|
2050
2113
|
if (config.gap && index < numChildren - 1) {
|
|
2051
|
-
return (jsxs(Fragment, { children: [jsxs("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: [child, isStacking && (jsx("div", { className: "mobile-gap-spacer", style: {
|
|
2114
|
+
return (jsxs(Fragment, { children: [jsxs("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: [child, isStacking && !isGapZero(config.gap) && (jsx("div", { className: "mobile-gap-spacer", style: {
|
|
2052
2115
|
display: "none",
|
|
2053
2116
|
fontSize: "0",
|
|
2054
2117
|
lineHeight: "0",
|
|
2055
2118
|
height: config.gap,
|
|
2056
|
-
|
|
2119
|
+
background: "transparent",
|
|
2120
|
+
}, children: "\u00A0" }))] }, `child-${index}`), !isGapZero(config.gap) && (jsx("td", { className: isStacking ? "desktop-gap-column" : undefined, width: config.gap, style: gapTdStyle, children: "\u00A0" }, `gap-${index}`))] }, `ctn:${index}`));
|
|
2057
2121
|
}
|
|
2058
2122
|
return (jsx("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: child }, `child-${index}`));
|
|
2059
2123
|
});
|
|
2060
2124
|
return (jsx("table", { "aria-label": `Container | Table Outer`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: {
|
|
2061
2125
|
position: "relative",
|
|
2062
2126
|
...outerTableStyle,
|
|
2063
|
-
}, children: jsx("tbody", { children: jsx("tr", { children: jsxs("td", { align: justifyAlign, children: [jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedWrapper } }), jsxs("table", { className: [
|
|
2127
|
+
}, ...rootBindingProps(bindings), children: jsx("tbody", { children: jsx("tr", { children: jsxs("td", { align: justifyAlign, children: [jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedWrapper } }), jsxs("table", { className: [
|
|
2064
2128
|
widthType === "fixed" ? "container-fixed-width" : undefined,
|
|
2065
2129
|
devMode ? "main-wrapper relative" : undefined,
|
|
2066
2130
|
]
|
|
@@ -2069,22 +2133,22 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2069
2133
|
width: "100%",
|
|
2070
2134
|
maxWidth: widthType === "fixed" ? config.width || "600px" : undefined,
|
|
2071
2135
|
borderCollapse: "collapse",
|
|
2072
|
-
}, width: containerWidthAttr, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: backgroundTdStyle, children: jsx("table", { "aria-label": `Container | Border Wrapper`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: borderTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: innerTdStyle, children: jsx("table", { "aria-label": `Container | Content Table`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: contentTableStyle, children: jsx("tbody", { children: jsx("tr", { children: rowElements }) }) }) }) }) }) }) }) }) }), !!devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }), jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedFooter } })] }) }) }) }));
|
|
2136
|
+
}, width: containerWidthAttr, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: backgroundTdStyle, children: jsx("table", { "aria-label": `Container | Border Wrapper`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: borderTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: innerTdStyle, children: jsx("table", { "aria-label": `Container | Content Table`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: contentTableStyle, children: jsx("tbody", { children: jsx("tr", { ...listBindingProps(bindings), children: rowElements }) }) }) }) }) }) }) }) }) }), !!devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }), jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedFooter } })] }) }) }) }));
|
|
2073
2137
|
}
|
|
2074
2138
|
var Container_default = memo(Container, arePropsEqual);
|
|
2075
2139
|
|
|
2076
|
-
function Divider({ config, devNode }) {
|
|
2140
|
+
function Divider({ config, devNode, bindings }) {
|
|
2077
2141
|
const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", hideOnMobile, } = config;
|
|
2078
2142
|
const heightPx = parseInt(height, 10) || 1;
|
|
2079
2143
|
// Parse margin into paddingTop / paddingBottom for the outer TD.
|
|
2080
2144
|
// Outlook ignores shorthand "20px 0" on TDs — must be explicit.
|
|
2081
|
-
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw] = margin.trim().split(/\s+/);
|
|
2145
|
+
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw,] = margin.trim().split(/\s+/);
|
|
2082
2146
|
const marginTop = marginTopRaw;
|
|
2083
2147
|
const marginBottom = marginBottomRaw !== null && marginBottomRaw !== void 0 ? marginBottomRaw : marginTopRaw; // "20px 0" → top=20px, bottom=20px
|
|
2084
2148
|
// Outlook requires align on the outer TD to correctly position
|
|
2085
2149
|
// a fixed-width inner table (e.g. width="300px").
|
|
2086
2150
|
const alignAttr = align === "left" ? "left" : align === "right" ? "right" : "center";
|
|
2087
|
-
return (jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2151
|
+
return (jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2088
2152
|
position: "relative", // dev overlay anchor
|
|
2089
2153
|
width: "100%",
|
|
2090
2154
|
borderCollapse: "collapse",
|
|
@@ -2181,7 +2245,13 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2181
2245
|
line-height: inherit !important;
|
|
2182
2246
|
}
|
|
2183
2247
|
body { background-color: ${backgroundColor} !important; }
|
|
2184
|
-
p {
|
|
2248
|
+
p {
|
|
2249
|
+
margin: 0;
|
|
2250
|
+
margin-block-start: 0px;
|
|
2251
|
+
margin-block-end: 0px;
|
|
2252
|
+
margin-inline-start: 0px;
|
|
2253
|
+
margin-inline-end: 0px;
|
|
2254
|
+
}
|
|
2185
2255
|
`;
|
|
2186
2256
|
const globalStyles = `
|
|
2187
2257
|
@media screen and (max-width: 768px) {
|
|
@@ -2403,8 +2473,56 @@ function injectLinkStyles(html, fallback) {
|
|
|
2403
2473
|
return result;
|
|
2404
2474
|
}
|
|
2405
2475
|
|
|
2406
|
-
|
|
2407
|
-
|
|
2476
|
+
// injectParagraphReset.ts
|
|
2477
|
+
const P_RESET_STYLE = [
|
|
2478
|
+
"margin:0",
|
|
2479
|
+
"margin-block-start:0px",
|
|
2480
|
+
"margin-block-end:0px",
|
|
2481
|
+
"margin-inline-start:0px",
|
|
2482
|
+
"margin-inline-end:0px",
|
|
2483
|
+
].join(";");
|
|
2484
|
+
function injectParagraphReset(html) {
|
|
2485
|
+
if (!html || !html.includes("<p"))
|
|
2486
|
+
return html;
|
|
2487
|
+
return html.replace(/<p(\s[^>]*)?>/gi, (_, attrs = "") => {
|
|
2488
|
+
var _a, _b;
|
|
2489
|
+
const existingStyle = (_b = (_a = /style\s*=\s*"([^"]*)"/i.exec(attrs)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : "";
|
|
2490
|
+
const mergedStyle = existingStyle
|
|
2491
|
+
? `${existingStyle};${P_RESET_STYLE}`
|
|
2492
|
+
: P_RESET_STYLE;
|
|
2493
|
+
const cleanAttrs = attrs.replace(/\s*style\s*=\s*"[^"]*"/i, "").trim();
|
|
2494
|
+
return cleanAttrs
|
|
2495
|
+
? `<p ${cleanAttrs} style="${mergedStyle}">`
|
|
2496
|
+
: `<p style="${mergedStyle}">`;
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
// Helper to build link href based on innerLink type
|
|
2501
|
+
function buildLinkHref$3(innerLink) {
|
|
2502
|
+
if (!innerLink || innerLink.type === "none")
|
|
2503
|
+
return null;
|
|
2504
|
+
switch (innerLink.type) {
|
|
2505
|
+
case "url":
|
|
2506
|
+
return innerLink.url || null;
|
|
2507
|
+
case "email":
|
|
2508
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
2509
|
+
case "phone":
|
|
2510
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
2511
|
+
case "anchor":
|
|
2512
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
2513
|
+
case "page_top":
|
|
2514
|
+
return "#top";
|
|
2515
|
+
case "page_bottom":
|
|
2516
|
+
return "#bottom";
|
|
2517
|
+
default:
|
|
2518
|
+
return null;
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
function Heading({ config, devMode, children, bindings }) {
|
|
2522
|
+
const { text, level = "h1", padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, wordBreak, whiteSpace, innerLink, } = config;
|
|
2523
|
+
// Resolve href and target from innerLink
|
|
2524
|
+
const href = buildLinkHref$3(innerLink);
|
|
2525
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2408
2526
|
// Determine the content to render
|
|
2409
2527
|
const content = text !== null && text !== void 0 ? text : children;
|
|
2410
2528
|
const isString = typeof content === "string";
|
|
@@ -2437,16 +2555,21 @@ function Heading({ config, devMode, children }) {
|
|
|
2437
2555
|
["msoLineHeightRule"]: "exactly",
|
|
2438
2556
|
};
|
|
2439
2557
|
const processedHtml = isString
|
|
2440
|
-
? injectLinkStyles(content, headingStyle)
|
|
2558
|
+
? injectParagraphReset(injectLinkStyles(content, headingStyle))
|
|
2441
2559
|
: "";
|
|
2442
2560
|
// Dynamically create the Heading element
|
|
2443
2561
|
const HeadingTag = level;
|
|
2562
|
+
const headingElement = isString ? (jsx(HeadingTag, { style: headingStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsx(HeadingTag, { style: headingStyle, children: content }));
|
|
2444
2563
|
return (
|
|
2445
2564
|
// Wrap the heading content in a table for padding/width/background management.
|
|
2446
|
-
jsx("table", { "aria-label": "Heading Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2565
|
+
jsx("table", { "aria-label": "Heading Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2447
2566
|
width: "100%",
|
|
2448
2567
|
borderCollapse: "collapse",
|
|
2449
|
-
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children:
|
|
2568
|
+
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children: href && !devMode ? (jsx("a", { href: href, target: target, ...(target === "_blank" ? { rel: "noopener noreferrer" } : {}), style: {
|
|
2569
|
+
display: "block",
|
|
2570
|
+
textDecoration: "none",
|
|
2571
|
+
color: "inherit",
|
|
2572
|
+
}, children: headingElement })) : (headingElement) }) }) }) }));
|
|
2450
2573
|
}
|
|
2451
2574
|
var Heading_default = memo(Heading, arePropsEqual);
|
|
2452
2575
|
|
|
@@ -2471,7 +2594,7 @@ function Html({ children, backgroundColor = "#ffffff", }) {
|
|
|
2471
2594
|
}
|
|
2472
2595
|
|
|
2473
2596
|
// Helper to build link href based on innerLink type
|
|
2474
|
-
function buildLinkHref$
|
|
2597
|
+
function buildLinkHref$2(innerLink) {
|
|
2475
2598
|
if (!innerLink || innerLink.type === "none")
|
|
2476
2599
|
return null;
|
|
2477
2600
|
switch (innerLink.type) {
|
|
@@ -2531,11 +2654,15 @@ function getBorderStyleString$1(border) {
|
|
|
2531
2654
|
styles.push(`border-left:${border.left.width} ${border.left.style} ${border.left.color} !important;`);
|
|
2532
2655
|
return styles.join(" ");
|
|
2533
2656
|
}
|
|
2534
|
-
function Image({ config, devNode, devMode }) {
|
|
2657
|
+
function Image({ config, devNode, devMode, bindings }) {
|
|
2535
2658
|
var _a, _b;
|
|
2536
|
-
const { src, alt, innerLink, mobile } = config;
|
|
2659
|
+
const { src: originalSrc, alt, innerLink, mobile } = config;
|
|
2660
|
+
// In dev mode, if there's no src, use the placeholder
|
|
2661
|
+
const src = devMode && !originalSrc
|
|
2662
|
+
? "https://placehold.co/300x200?text=select+an+image&font=poppins"
|
|
2663
|
+
: originalSrc;
|
|
2537
2664
|
// Resolve href and target from innerLink
|
|
2538
|
-
const href = buildLinkHref$
|
|
2665
|
+
const href = buildLinkHref$2(innerLink);
|
|
2539
2666
|
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2540
2667
|
const seed = src + (alt || "");
|
|
2541
2668
|
const instanceId = seed
|
|
@@ -2549,43 +2676,37 @@ function Image({ config, devNode, devMode }) {
|
|
|
2549
2676
|
const widthAttr = desktopWidth.replace("px", "");
|
|
2550
2677
|
const heightAttr = (_a = config.height) === null || _a === void 0 ? void 0 : _a.replace("px", "");
|
|
2551
2678
|
// Determine the table's "initial" width.
|
|
2552
|
-
// If it's 300px, the table should be 300px, not 100%.
|
|
2553
2679
|
const tableWidth = isPercent ? desktopWidth : `${widthAttr}px`;
|
|
2554
|
-
//
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2680
|
+
// Calculate width attribute for Outlook
|
|
2681
|
+
let imgWidthAttr;
|
|
2682
|
+
if (config.outlookWidth) {
|
|
2683
|
+
// Use explicit outlookWidth if provided
|
|
2684
|
+
imgWidthAttr = parseInt(config.outlookWidth, 10);
|
|
2685
|
+
}
|
|
2686
|
+
else if (isPercent) {
|
|
2687
|
+
// For percentage widths, use maxWidth as fallback for Outlook
|
|
2688
|
+
const maxWidthPx = ((_b = config.maxWidth) === null || _b === void 0 ? void 0 : _b.endsWith("px"))
|
|
2689
|
+
? parseInt(config.maxWidth, 10)
|
|
2690
|
+
: undefined;
|
|
2691
|
+
imgWidthAttr = maxWidthPx !== null && maxWidthPx !== void 0 ? maxWidthPx : undefined;
|
|
2692
|
+
}
|
|
2693
|
+
else {
|
|
2694
|
+
// For fixed pixel widths, use that value
|
|
2695
|
+
imgWidthAttr = widthAttr ? parseInt(widthAttr, 10) : undefined;
|
|
2696
|
+
}
|
|
2697
|
+
// 2. Mobile Overrides
|
|
2571
2698
|
let mobileCss = "";
|
|
2572
2699
|
if (mobile) {
|
|
2573
|
-
|
|
2574
|
-
const wrapRules = [
|
|
2575
|
-
// Always reset min-width so the px lock from desktop can be overridden
|
|
2576
|
-
"min-width: 0 !important;",
|
|
2577
|
-
];
|
|
2700
|
+
const wrapRules = ["min-width: 0 !important;"];
|
|
2578
2701
|
if (mobile.width !== undefined)
|
|
2579
2702
|
wrapRules.push(`width: ${mobile.width} !important;`);
|
|
2580
2703
|
if (mobile.maxWidth !== undefined)
|
|
2581
2704
|
wrapRules.push(`max-width: ${mobile.maxWidth} !important;`);
|
|
2582
|
-
// .td-${imgClass} rules
|
|
2583
2705
|
const tdRules = [];
|
|
2584
2706
|
if (mobile.padding !== undefined)
|
|
2585
2707
|
tdRules.push(`padding: ${mobile.padding} !important;`);
|
|
2586
2708
|
if (mobile.backgroundColor !== undefined)
|
|
2587
2709
|
tdRules.push(`background-color: ${mobile.backgroundColor} !important;`);
|
|
2588
|
-
// .${imgClass} rules
|
|
2589
2710
|
const imgRules = [];
|
|
2590
2711
|
if (mobile.width !== undefined)
|
|
2591
2712
|
imgRules.push(`width: ${mobile.width} !important;`);
|
|
@@ -2608,7 +2729,6 @@ function Image({ config, devNode, devMode }) {
|
|
|
2608
2729
|
mobileCss = `
|
|
2609
2730
|
@media screen and (max-width: 768px) {
|
|
2610
2731
|
.wrap-${imgClass} {
|
|
2611
|
-
/* This breaks the px lock from desktop and makes it fluid */
|
|
2612
2732
|
${wrapRules.join("\n ")}
|
|
2613
2733
|
}
|
|
2614
2734
|
.td-${imgClass} {
|
|
@@ -2634,9 +2754,27 @@ function Image({ config, devNode, devMode }) {
|
|
|
2634
2754
|
objectPosition: config.objectPosition,
|
|
2635
2755
|
};
|
|
2636
2756
|
const imageElement = (jsx("img", { src: src, alt: alt, width: imgWidthAttr, height: heightAttr !== "auto" ? heightAttr : undefined, className: imgClass, style: imgStyle, draggable: !devMode }));
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2757
|
+
// Outlook Classic wrapper - only applied when outlookWidth is explicitly set
|
|
2758
|
+
// OR when we need to constrain a percentage-width image in Outlook
|
|
2759
|
+
const needsOutlookWrapper = config.outlookWidth || (isPercent && imgWidthAttr);
|
|
2760
|
+
const finalImageElement = needsOutlookWrapper ? (jsxs(Fragment$1, { children: [jsx("style", { dangerouslySetInnerHTML: {
|
|
2761
|
+
__html: `</style>` +
|
|
2762
|
+
`<!--[if mso]>` +
|
|
2763
|
+
`<table cellpadding="0" cellspacing="0" border="0" style="width: ${imgWidthAttr}px;">` +
|
|
2764
|
+
`<tr>` +
|
|
2765
|
+
`<td style="padding: 0; margin: 0;" width="${imgWidthAttr}">` +
|
|
2766
|
+
`<img src="${src}" alt="${alt || ""}" width="${imgWidthAttr}" height="${heightAttr !== "auto" ? heightAttr : ""}" style="display: block; width: 100%; height: auto;" />` +
|
|
2767
|
+
`</td>` +
|
|
2768
|
+
`</tr>` +
|
|
2769
|
+
`</table>` +
|
|
2770
|
+
`<![endif]-->` +
|
|
2771
|
+
`<!--[if !mso]><!-->` +
|
|
2772
|
+
`<style>`,
|
|
2773
|
+
} }), imageElement, jsx("style", { dangerouslySetInnerHTML: {
|
|
2774
|
+
__html: `</style>` + `<!--<![endif]-->` + `<style>`,
|
|
2775
|
+
} })] })) : (imageElement);
|
|
2776
|
+
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", ...rootBindingProps(bindings), style: {
|
|
2777
|
+
width: tableWidth,
|
|
2640
2778
|
maxWidth: "100%",
|
|
2641
2779
|
borderCollapse: "collapse",
|
|
2642
2780
|
margin: "0 auto",
|
|
@@ -2645,10 +2783,10 @@ function Image({ config, devNode, devMode }) {
|
|
|
2645
2783
|
backgroundColor: config.backgroundColor,
|
|
2646
2784
|
fontSize: "0",
|
|
2647
2785
|
lineHeight: "0",
|
|
2648
|
-
width: tableWidth,
|
|
2786
|
+
width: tableWidth,
|
|
2649
2787
|
}, children: href && !devMode ? (jsx("a", { href: href, target: target, ...(target === "_blank"
|
|
2650
2788
|
? { rel: "noopener noreferrer" }
|
|
2651
|
-
: {}), style: { display: "block", width: "100%" }, children:
|
|
2789
|
+
: {}), style: { display: "block", width: "100%" }, children: finalImageElement })) : (finalImageElement) }) }) }), devMode && !!devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] })] }));
|
|
2652
2790
|
}
|
|
2653
2791
|
var Image_default = memo(Image, arePropsEqual);
|
|
2654
2792
|
|
|
@@ -2717,7 +2855,21 @@ function getHrefFromInnerLink(innerLink) {
|
|
|
2717
2855
|
return undefined;
|
|
2718
2856
|
}
|
|
2719
2857
|
}
|
|
2720
|
-
|
|
2858
|
+
/**
|
|
2859
|
+
* Resolves the width for a child <td> at the given index based on layoutColumns.
|
|
2860
|
+
*
|
|
2861
|
+
* - "equal" → equal percentage share across all children
|
|
2862
|
+
* - string[] → explicit value at the matching index (px, %, or mixed)
|
|
2863
|
+
* - undefined → undefined, so no width attribute is set (retrocompat)
|
|
2864
|
+
*/
|
|
2865
|
+
function resolveChildColumnWidth(layoutColumns, index, numChildren) {
|
|
2866
|
+
if (!layoutColumns)
|
|
2867
|
+
return undefined;
|
|
2868
|
+
if (layoutColumns === "equal")
|
|
2869
|
+
return `${100 / numChildren}%`;
|
|
2870
|
+
return layoutColumns[index];
|
|
2871
|
+
}
|
|
2872
|
+
function Row({ children, config, devNode, devMode, bindings }) {
|
|
2721
2873
|
var _a, _b, _c, _d, _e, _f;
|
|
2722
2874
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2723
2875
|
const numChildren = childrenArray.length;
|
|
@@ -2728,6 +2880,9 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2728
2880
|
// / mobile-gap-spacer class names so that stacking works via non-@media CSS
|
|
2729
2881
|
// rules that survive Gmail's stylesheet stripping.
|
|
2730
2882
|
const isStacking = ((_b = config.mobile) === null || _b === void 0 ? void 0 : _b.wrap) === true && numChildren > 1;
|
|
2883
|
+
// Whether layoutColumns is active. When true, table-layout:fixed is applied
|
|
2884
|
+
// to the content table so Outlook Classic honours the declared column widths.
|
|
2885
|
+
const hasLayoutColumns = config.layoutColumns !== undefined;
|
|
2731
2886
|
// 1. Outer TD: Background, Border Radius, Width, Height.
|
|
2732
2887
|
const backgroundTdStyle = {
|
|
2733
2888
|
backgroundColor: config.backgroundColor,
|
|
@@ -2768,24 +2923,34 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2768
2923
|
// Content table fills available space, giving Outlook Classic a hard
|
|
2769
2924
|
// boundary so text children get a constrained box and line wrapping
|
|
2770
2925
|
// triggers correctly. Use for rows containing text + image layouts.
|
|
2926
|
+
//
|
|
2927
|
+
// layoutColumns (any value) → additionally applies table-layout: fixed
|
|
2928
|
+
// so Outlook Classic honours the per-child width declarations.
|
|
2929
|
+
// Compatible with both fillWidth modes.
|
|
2771
2930
|
const contentTableStyle = {
|
|
2772
|
-
|
|
2931
|
+
// When layoutColumns is active, force 100% so Outlook Classic has a
|
|
2932
|
+
// concrete boundary to resolve percentage column widths against.
|
|
2933
|
+
// table-layout:fixed is meaningless without a fixed reference width.
|
|
2934
|
+
width: hasLayoutColumns || config.fillWidth ? "100%" : "auto",
|
|
2773
2935
|
height: "100%",
|
|
2774
2936
|
borderCollapse: "collapse",
|
|
2775
2937
|
minWidth: "1px",
|
|
2776
|
-
...(!config.fillWidth &&
|
|
2938
|
+
...(!config.fillWidth &&
|
|
2939
|
+
!hasLayoutColumns && { maxWidth: config.width || "100%" }),
|
|
2940
|
+
...(hasLayoutColumns && { tableLayout: "fixed" }),
|
|
2777
2941
|
};
|
|
2778
2942
|
// 5. Gap TD.
|
|
2779
2943
|
const gapTdStyle = {
|
|
2780
2944
|
width: config.gap || "0",
|
|
2781
2945
|
lineHeight: "1px",
|
|
2782
2946
|
fontSize: "1px",
|
|
2947
|
+
background: "transparent",
|
|
2783
2948
|
};
|
|
2784
2949
|
const tdAlign = config.justifyContent
|
|
2785
2950
|
? justifyMap$1[config.justifyContent]
|
|
2786
2951
|
: "left";
|
|
2787
2952
|
const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
|
|
2788
|
-
const content = (jsxs("table", { "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2953
|
+
const content = (jsxs("table", { "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...(!href ? rootBindingProps(bindings) : {}), style: {
|
|
2789
2954
|
position: "relative",
|
|
2790
2955
|
width: config.width || "100%",
|
|
2791
2956
|
height: config.height,
|
|
@@ -2794,32 +2959,44 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2794
2959
|
width: "100%",
|
|
2795
2960
|
height: "100%",
|
|
2796
2961
|
borderCollapse: "collapse",
|
|
2797
|
-
}, 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-wrap": ((_f = config.mobile) === null || _f === void 0 ? void 0 : _f.wrap) ? "true" : undefined, "data-gap": config.gap, children: jsx("tbody", { children: jsx("tr", { className: "content-tr", children: childrenArray.map((child, index) =>
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2962
|
+
}, 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-wrap": ((_f = config.mobile) === null || _f === void 0 ? void 0 : _f.wrap) ? "true" : undefined, "data-gap": config.gap, children: jsx("tbody", { children: jsx("tr", { className: "content-tr", ...listBindingProps(bindings), children: childrenArray.map((child, index) => {
|
|
2963
|
+
// Resolve the column width for this child based on
|
|
2964
|
+
// layoutColumns. undefined when layoutColumns is not set,
|
|
2965
|
+
// preserving the original behaviour (retrocompat).
|
|
2966
|
+
const columnWidth = resolveChildColumnWidth(config.layoutColumns, index, numChildren);
|
|
2967
|
+
return (jsxs(Fragment, { children: [jsxs("td", { align: tdAlign, ...(columnWidth && {
|
|
2968
|
+
width: columnWidth,
|
|
2969
|
+
}), style: {
|
|
2970
|
+
verticalAlign: tdValign,
|
|
2971
|
+
textAlign: tdAlign,
|
|
2972
|
+
padding: "0",
|
|
2973
|
+
margin: "0",
|
|
2974
|
+
...(columnWidth && {
|
|
2975
|
+
width: columnWidth,
|
|
2976
|
+
}),
|
|
2977
|
+
},
|
|
2978
|
+
// Mirror of Container's stack-td pattern: when isStacking,
|
|
2979
|
+
// the non-@media .stack-td rule forces display:block +
|
|
2980
|
+
// width:100% on each child, which survives Gmail's
|
|
2981
|
+
// @media stripping and achieves true mobile stacking.
|
|
2982
|
+
className: `child-cell${isStacking ? " stack-td" : ""}`, children: [child, isStacking &&
|
|
2983
|
+
index < numChildren - 1 &&
|
|
2984
|
+
config.gap && (jsx("div", { className: "mobile-gap-spacer", style: {
|
|
2985
|
+
display: "none",
|
|
2986
|
+
fontSize: "0",
|
|
2987
|
+
lineHeight: "0",
|
|
2988
|
+
height: config.gap,
|
|
2989
|
+
background: "transparent",
|
|
2990
|
+
}, children: "\u00A0" }))] }), index < numChildren - 1 &&
|
|
2991
|
+
config.gap && (jsx("td", { width: config.gap, style: gapTdStyle,
|
|
2992
|
+
// Mirror of Container's desktop-gap-column pattern:
|
|
2993
|
+
// when isStacking, the non-@media .desktop-gap-column
|
|
2994
|
+
// rule collapses the between-column gap td so it does
|
|
2995
|
+
// not create phantom space while children are stacked.
|
|
2996
|
+
className: `row-gap-td${isStacking ? " desktop-gap-column" : ""}`, children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`));
|
|
2997
|
+
}) }) }) }) }) }) }) }) }) }) }) }) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2821
2998
|
if (href && !devMode) {
|
|
2822
|
-
return (jsx("a", { href: href, ...({ target }), style: {
|
|
2999
|
+
return (jsx("a", { href: href, ...({ target }), ...rootBindingProps(bindings), style: {
|
|
2823
3000
|
textDecoration: "none",
|
|
2824
3001
|
color: "inherit",
|
|
2825
3002
|
display: "block",
|
|
@@ -2864,10 +3041,10 @@ function getBorderStyle$1(border) {
|
|
|
2864
3041
|
}
|
|
2865
3042
|
return style;
|
|
2866
3043
|
}
|
|
2867
|
-
const Section = ({ config, children, devNode, }) => {
|
|
3044
|
+
const Section = ({ config, children, devNode, bindings, }) => {
|
|
2868
3045
|
var _a, _b, _c;
|
|
2869
3046
|
const { sectionType, padding } = config;
|
|
2870
|
-
return (jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
3047
|
+
return (jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2871
3048
|
position: "relative",
|
|
2872
3049
|
width: "100%",
|
|
2873
3050
|
backgroundColor: config.backgroundColor,
|
|
@@ -2880,58 +3057,84 @@ const Section = ({ config, children, devNode, }) => {
|
|
|
2880
3057
|
backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
|
|
2881
3058
|
}, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: {
|
|
2882
3059
|
padding: padding,
|
|
2883
|
-
}, children: children }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children:
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
3060
|
+
}, ...listBindingProps(bindings), children: children }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: jsxs("span", { style: {
|
|
3061
|
+
backgroundColor: "black",
|
|
3062
|
+
color: "white",
|
|
3063
|
+
padding: "4px",
|
|
3064
|
+
fontSize: "14px",
|
|
3065
|
+
position: "absolute",
|
|
3066
|
+
left: 0,
|
|
3067
|
+
top: 0,
|
|
3068
|
+
}, children: ["Section | ", sectionType] }) }) }) }))] }));
|
|
2892
3069
|
};
|
|
2893
3070
|
var Section_default = memo(Section, arePropsEqual);
|
|
2894
3071
|
|
|
2895
|
-
function Spacer({ config, devNode }) {
|
|
2896
|
-
|
|
3072
|
+
function Spacer({ config, devNode, bindings }) {
|
|
3073
|
+
var _a, _b, _c;
|
|
3074
|
+
const { height, hideOnMobile, backgroundColor, backgroundImage } = config;
|
|
2897
3075
|
// 1. Spacer Table Style
|
|
2898
3076
|
const spacerTableStyle = {
|
|
2899
|
-
// Crucial for compatibility: Ensures no background or border interference
|
|
2900
|
-
backgroundColor: "transparent",
|
|
2901
3077
|
borderCollapse: "collapse",
|
|
2902
|
-
border: "0",
|
|
2903
3078
|
width: "100%",
|
|
2904
|
-
// Note the CSS standard dash convention: 'mso-table-lspace'
|
|
2905
|
-
// ["mso-table-lspace" as string]: "0pt",
|
|
2906
|
-
["msoTableLspace"]: "0pt",
|
|
2907
|
-
// ["mso-table-rspace" as string]: "0pt",
|
|
2908
|
-
["msoTableRspace"]: "0pt",
|
|
2909
3079
|
};
|
|
2910
3080
|
// 2. Spacer TD Style: The element that creates the actual vertical space
|
|
2911
3081
|
const spacerTdStyle = {
|
|
2912
3082
|
height: height,
|
|
2913
|
-
|
|
3083
|
+
maxHeight: height,
|
|
2914
3084
|
fontSize: "0",
|
|
2915
3085
|
lineHeight: "0",
|
|
2916
3086
|
padding: "0",
|
|
3087
|
+
margin: "0",
|
|
3088
|
+
border: "none",
|
|
3089
|
+
color: "transparent",
|
|
3090
|
+
// Background applied at TD level for Outlook Classic compatibility
|
|
3091
|
+
...(backgroundColor && { backgroundColor }),
|
|
3092
|
+
...(backgroundImage && {
|
|
3093
|
+
backgroundImage: `url(${backgroundImage.src})`,
|
|
3094
|
+
backgroundRepeat: (_a = backgroundImage.repeat) !== null && _a !== void 0 ? _a : "no-repeat",
|
|
3095
|
+
backgroundSize: (_b = backgroundImage.size) !== null && _b !== void 0 ? _b : "cover",
|
|
3096
|
+
backgroundPosition: (_c = backgroundImage.position) !== null && _c !== void 0 ? _c : "center",
|
|
3097
|
+
}),
|
|
2917
3098
|
};
|
|
2918
3099
|
// Parse height for the HTML attribute
|
|
2919
3100
|
const spacerHeightAttribute = parseInt(height, 10) || 1;
|
|
2920
|
-
return (
|
|
2921
|
-
// Outer table ensures the spacer spans the full width of its container
|
|
2922
|
-
jsxs("table", { "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
3101
|
+
return (jsxs("table", { "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2923
3102
|
// --- Start dev
|
|
2924
3103
|
position: "relative",
|
|
2925
3104
|
// --- End dev
|
|
2926
3105
|
...spacerTableStyle,
|
|
2927
|
-
}, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: spacerTdStyle,
|
|
2928
|
-
|
|
2929
|
-
|
|
3106
|
+
}, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: spacerTdStyle, height: spacerHeightAttribute, ...(backgroundColor && !backgroundImage
|
|
3107
|
+
? { bgcolor: backgroundColor }
|
|
3108
|
+
: {}) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2930
3109
|
}
|
|
2931
3110
|
var Spacer_default = memo(Spacer, arePropsEqual);
|
|
2932
3111
|
|
|
2933
|
-
|
|
2934
|
-
|
|
3112
|
+
// Helper to build link href based on innerLink type
|
|
3113
|
+
function buildLinkHref$1(innerLink) {
|
|
3114
|
+
if (!innerLink || innerLink.type === "none")
|
|
3115
|
+
return null;
|
|
3116
|
+
switch (innerLink.type) {
|
|
3117
|
+
case "url":
|
|
3118
|
+
return innerLink.url || null;
|
|
3119
|
+
case "email":
|
|
3120
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
3121
|
+
case "phone":
|
|
3122
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
3123
|
+
case "anchor":
|
|
3124
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
3125
|
+
case "page_top":
|
|
3126
|
+
return "#top";
|
|
3127
|
+
case "page_bottom":
|
|
3128
|
+
return "#bottom";
|
|
3129
|
+
default:
|
|
3130
|
+
return null;
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
function Text({ config, devMode, children, bindings }) {
|
|
3134
|
+
const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth, innerLink, } = config;
|
|
3135
|
+
// Resolve href and target from innerLink
|
|
3136
|
+
const href = buildLinkHref$1(innerLink);
|
|
3137
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2935
3138
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
2936
3139
|
// When maxWidth is set, this TD stays at width: 100% so it always fills
|
|
2937
3140
|
// its parent — the inner maxWidth table (see below) does the actual
|
|
@@ -2984,26 +3187,31 @@ function Text({ config, devMode, children }) {
|
|
|
2984
3187
|
? injectLinkStyles(content, contentStyle)
|
|
2985
3188
|
: "";
|
|
2986
3189
|
const innerContent = isString ? (jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsx("div", { style: contentStyle, children: content }));
|
|
2987
|
-
|
|
3190
|
+
const wrappedContent = maxWidth ? (
|
|
3191
|
+
/*
|
|
3192
|
+
* maxWidth wrapper — Outlook Classic compatibility pattern:
|
|
3193
|
+
*
|
|
3194
|
+
* <center> instructs the Word rendering engine to horizontally
|
|
3195
|
+
* centre its child block, equivalent to margin: 0 auto in CSS.
|
|
3196
|
+
*
|
|
3197
|
+
* The inner table carries the `width` HTML attribute set to the
|
|
3198
|
+
* maxWidth value. Outlook Classic reads `width` as a hard pixel
|
|
3199
|
+
* cap; it has no concept of max-width so this is the only lever
|
|
3200
|
+
* available. Modern clients receive the CSS max-width on the
|
|
3201
|
+
* same table and behave correctly.
|
|
3202
|
+
*
|
|
3203
|
+
* The outer TD remains at width: 100% so it always fills its
|
|
3204
|
+
* parent cell in every client — only the inner content is capped.
|
|
3205
|
+
*/
|
|
3206
|
+
jsx("center", { children: jsx("table", { "aria-label": "Text Max Width Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, width: maxWidth, style: maxWidthTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { children: innerContent }) }) }) }) })) : (innerContent);
|
|
3207
|
+
return (jsx("table", { "aria-label": "Text Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2988
3208
|
width: "100%",
|
|
2989
3209
|
borderCollapse: "collapse",
|
|
2990
|
-
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children:
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
* centre its child block, equivalent to margin: 0 auto in CSS.
|
|
2996
|
-
*
|
|
2997
|
-
* The inner table carries the `width` HTML attribute set to the
|
|
2998
|
-
* maxWidth value. Outlook Classic reads `width` as a hard pixel
|
|
2999
|
-
* cap; it has no concept of max-width so this is the only lever
|
|
3000
|
-
* available. Modern clients receive the CSS max-width on the
|
|
3001
|
-
* same table and behave correctly.
|
|
3002
|
-
*
|
|
3003
|
-
* The outer TD remains at width: 100% so it always fills its
|
|
3004
|
-
* parent cell in every client — only the inner content is capped.
|
|
3005
|
-
*/
|
|
3006
|
-
jsx("center", { children: jsx("table", { "aria-label": "Text Max Width Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, width: maxWidth, style: maxWidthTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { children: innerContent }) }) }) }) })) : (innerContent) }) }) }) }));
|
|
3210
|
+
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children: href && !devMode ? (jsx("a", { href: href, target: target, ...(target === "_blank" ? { rel: "noopener noreferrer" } : {}), style: {
|
|
3211
|
+
display: "block",
|
|
3212
|
+
textDecoration: "none",
|
|
3213
|
+
color: "inherit",
|
|
3214
|
+
}, children: wrappedContent })) : (wrappedContent) }) }) }) }));
|
|
3007
3215
|
}
|
|
3008
3216
|
var Text_default = memo(Text, arePropsEqual);
|
|
3009
3217
|
|
|
@@ -3129,7 +3337,7 @@ function buildLinkHref(innerLink) {
|
|
|
3129
3337
|
return null;
|
|
3130
3338
|
}
|
|
3131
3339
|
}
|
|
3132
|
-
function Icon({ config, devNode, devMode, children }) {
|
|
3340
|
+
function Icon({ config, devNode, devMode, children, bindings }) {
|
|
3133
3341
|
const {
|
|
3134
3342
|
// base64Source,
|
|
3135
3343
|
width, height, backgroundColor, padding = "0", borderRadius = "0", border, innerLink, justifyContent = "center", } = config;
|
|
@@ -3264,7 +3472,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
3264
3472
|
<!--<![endif]-->
|
|
3265
3473
|
`
|
|
3266
3474
|
: null;
|
|
3267
|
-
return (jsxs("table", { "aria-label": "Icon", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, style: {
|
|
3475
|
+
return (jsxs("table", { "aria-label": "Icon", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, ...rootBindingProps(bindings), style: {
|
|
3268
3476
|
// --- Start dev
|
|
3269
3477
|
position: "relative",
|
|
3270
3478
|
// --- End dev
|