@pagenflow/email 1.4.6 → 1.4.8
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 +4 -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 +13 -1
- package/dist/components/utils/bindingAttribute.d.ts +38 -0
- package/dist/components/utils/linearizeStyle.d.ts +10 -0
- package/dist/index.cjs.js +368 -138
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +368 -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.cjs.js
CHANGED
|
@@ -1533,6 +1533,57 @@ function arePropsEqual(prevProps, nextProps) {
|
|
|
1533
1533
|
return isEqual(prevProps, nextProps);
|
|
1534
1534
|
}
|
|
1535
1535
|
|
|
1536
|
+
/**
|
|
1537
|
+
* bindingAttribute.ts
|
|
1538
|
+
* -------------------
|
|
1539
|
+
* Serialises DataBindings into discrete HTML attributes:
|
|
1540
|
+
*
|
|
1541
|
+
* data-bind-if → visible condition → stamped on the root element
|
|
1542
|
+
* data-bind-list → repeater (dataList + itemAlias) → stamped on the
|
|
1543
|
+
* direct parent of the children loop, NOT the root
|
|
1544
|
+
* data-bind → propertyMap → stamped on the root element
|
|
1545
|
+
*
|
|
1546
|
+
* Keeping the three concerns in separate attributes lets the post-processor
|
|
1547
|
+
* handle them independently without ambiguity.
|
|
1548
|
+
*/
|
|
1549
|
+
// ─── Root element props (visible + propertyMap) ───────────────────────────────
|
|
1550
|
+
/**
|
|
1551
|
+
* Props to spread onto the component's root element.
|
|
1552
|
+
* Carries `data-bind-if` and/or `data-bind` (propertyMap).
|
|
1553
|
+
*/
|
|
1554
|
+
function rootBindingProps(bindings) {
|
|
1555
|
+
if (!bindings)
|
|
1556
|
+
return {};
|
|
1557
|
+
const props = {};
|
|
1558
|
+
if (bindings.visible) {
|
|
1559
|
+
props['data-bind-if'] = bindings.visible;
|
|
1560
|
+
}
|
|
1561
|
+
if (bindings.propertyMap && Object.keys(bindings.propertyMap).length) {
|
|
1562
|
+
props['data-bind'] = JSON.stringify({ propertyMap: bindings.propertyMap });
|
|
1563
|
+
}
|
|
1564
|
+
return props;
|
|
1565
|
+
}
|
|
1566
|
+
// ─── List wrapper props (dataList + itemAlias) ────────────────────────────────
|
|
1567
|
+
/**
|
|
1568
|
+
* Props to spread onto the *direct parent* of the children loop.
|
|
1569
|
+
* Carries `data-bind-list` only when a repeater is defined.
|
|
1570
|
+
*
|
|
1571
|
+
* Usage inside a component:
|
|
1572
|
+
* <tbody {...listBindingProps(bindings)}>
|
|
1573
|
+
* {children}
|
|
1574
|
+
* </tbody>
|
|
1575
|
+
*/
|
|
1576
|
+
function listBindingProps(bindings) {
|
|
1577
|
+
if (!(bindings === null || bindings === void 0 ? void 0 : bindings.dataList))
|
|
1578
|
+
return {};
|
|
1579
|
+
return {
|
|
1580
|
+
'data-bind-list': JSON.stringify({
|
|
1581
|
+
dataList: bindings.dataList,
|
|
1582
|
+
...(bindings.itemAlias && { itemAlias: bindings.itemAlias }),
|
|
1583
|
+
}),
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1536
1587
|
// Map alignment to HTML 'align' attribute
|
|
1537
1588
|
const justifyMap$3 = {
|
|
1538
1589
|
start: "left",
|
|
@@ -1540,7 +1591,7 @@ const justifyMap$3 = {
|
|
|
1540
1591
|
end: "right",
|
|
1541
1592
|
};
|
|
1542
1593
|
// Helper to build link href based on innerLink type (mirrors Icon component)
|
|
1543
|
-
function buildLinkHref$
|
|
1594
|
+
function buildLinkHref$4(innerLink) {
|
|
1544
1595
|
if (!innerLink || innerLink.type === "none")
|
|
1545
1596
|
return null;
|
|
1546
1597
|
switch (innerLink.type) {
|
|
@@ -1594,10 +1645,10 @@ function getBorderStyleString$2(border) {
|
|
|
1594
1645
|
}
|
|
1595
1646
|
return styles.join(" ");
|
|
1596
1647
|
}
|
|
1597
|
-
function Button({ config, devMode }) {
|
|
1648
|
+
function Button({ config, devMode, bindings }) {
|
|
1598
1649
|
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
1650
|
// Resolve href from innerLink
|
|
1600
|
-
const href = buildLinkHref$
|
|
1651
|
+
const href = buildLinkHref$4(innerLink);
|
|
1601
1652
|
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
1602
1653
|
// Sanitize fontFamily early so safeFontFamily is available for all paths below.
|
|
1603
1654
|
const safeFontFamily = fontFamily
|
|
@@ -1681,7 +1732,7 @@ function Button({ config, devMode }) {
|
|
|
1681
1732
|
.join(" ");
|
|
1682
1733
|
return (
|
|
1683
1734
|
// Wrapper table for alignment - maintains proper positioning for hover indicators
|
|
1684
|
-
jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1735
|
+
jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
1685
1736
|
width: "100%",
|
|
1686
1737
|
borderCollapse: "collapse",
|
|
1687
1738
|
boxSizing: "border-box",
|
|
@@ -1789,7 +1840,7 @@ function getBorderStyle$5(border) {
|
|
|
1789
1840
|
}
|
|
1790
1841
|
return style;
|
|
1791
1842
|
}
|
|
1792
|
-
function Column({ children, config, devNode }) {
|
|
1843
|
+
function Column({ children, config, devNode, bindings }) {
|
|
1793
1844
|
var _a, _b, _c;
|
|
1794
1845
|
// Process children array for gap support
|
|
1795
1846
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
@@ -1803,6 +1854,9 @@ function Column({ children, config, devNode }) {
|
|
|
1803
1854
|
};
|
|
1804
1855
|
// 2. Outer TD style: Background and Border Radius (no border here).
|
|
1805
1856
|
// height is set so the TD occupies the full declared height.
|
|
1857
|
+
// When maxWidth is set, the outer TD stays at its normal width so it
|
|
1858
|
+
// always fills its parent — the inner maxWidth table (see below) does
|
|
1859
|
+
// the actual capping.
|
|
1806
1860
|
const outerTdStyle = {
|
|
1807
1861
|
width: config.width,
|
|
1808
1862
|
height: config.height,
|
|
@@ -1838,6 +1892,7 @@ function Column({ children, config, devNode }) {
|
|
|
1838
1892
|
// treat it as content-box height and add padding on top, causing the
|
|
1839
1893
|
// total to exceed the declared height in preview mode.
|
|
1840
1894
|
verticalAlign: config.alignItems ? alignMap$2[config.alignItems] : "top",
|
|
1895
|
+
background: "transparent",
|
|
1841
1896
|
};
|
|
1842
1897
|
// 4. Gap spacer style (used between children)
|
|
1843
1898
|
const gapSpacerStyle = {
|
|
@@ -1845,12 +1900,25 @@ function Column({ children, config, devNode }) {
|
|
|
1845
1900
|
lineHeight: "1px",
|
|
1846
1901
|
fontSize: "1px",
|
|
1847
1902
|
width: "100%",
|
|
1903
|
+
background: "transparent",
|
|
1904
|
+
};
|
|
1905
|
+
// 5. maxWidth constraining table style (modern clients).
|
|
1906
|
+
// The `width` HTML attribute on this table is what Outlook Classic
|
|
1907
|
+
// (Word engine) reads — it has no concept of max-width, but it does
|
|
1908
|
+
// honour the `width` attribute as a hard column cap.
|
|
1909
|
+
// The CSS max-width here handles modern web/email clients correctly.
|
|
1910
|
+
// <center> around it ensures the constrained block stays horizontally
|
|
1911
|
+
// centred in both the Word engine and standards-based renderers.
|
|
1912
|
+
const maxWidthTableStyle = {
|
|
1913
|
+
width: "100%",
|
|
1914
|
+
maxWidth: config.maxWidth,
|
|
1915
|
+
borderCollapse: "collapse",
|
|
1848
1916
|
};
|
|
1849
1917
|
// Main content rendering
|
|
1850
|
-
const renderContent = () => (jsxRuntime.jsx("table", { "aria-label": "Column Padding", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: innerTdStyle, valign: config.justifyContent ? vAlignMap[config.justifyContent] : "top", align: config.alignItems ? alignMap$2[config.alignItems] : "left",
|
|
1918
|
+
const renderContent = () => (jsxRuntime.jsx("table", { "aria-label": "Column Padding", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: innerTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: innerTdStyle, valign: config.justifyContent ? vAlignMap[config.justifyContent] : "top", align: config.alignItems ? alignMap$2[config.alignItems] : "left", ...(numChildren > 1 ? {} : listBindingProps(bindings)), children: numChildren > 1 ? (jsxRuntime.jsx("table", { "aria-label": "Column Gap Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1851
1919
|
width: "100%",
|
|
1852
1920
|
borderCollapse: "collapse",
|
|
1853
|
-
}, children: jsxRuntime.jsx("tbody", { children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
|
|
1921
|
+
}, children: jsxRuntime.jsx("tbody", { ...listBindingProps(bindings), children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
|
|
1854
1922
|
verticalAlign: config.alignItems
|
|
1855
1923
|
? alignMap$2[config.alignItems]
|
|
1856
1924
|
: "top",
|
|
@@ -1859,10 +1927,27 @@ function Column({ children, config, devNode }) {
|
|
|
1859
1927
|
: "top", align: config.alignItems
|
|
1860
1928
|
? alignMap$2[config.alignItems]
|
|
1861
1929
|
: "left", children: child }) }), index < numChildren - 1 && (jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: gapSpacerStyle, children: "\u00A0" }) }))] }, `col-child-${index}`))) }) })) : (children) }) }) }) }));
|
|
1862
|
-
return (jsxRuntime.jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1930
|
+
return (jsxRuntime.jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
1863
1931
|
position: "relative",
|
|
1864
1932
|
...outerTableStyle,
|
|
1865
|
-
}, ...(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:
|
|
1933
|
+
}, ...(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: config.maxWidth ? (
|
|
1934
|
+
/*
|
|
1935
|
+
* maxWidth wrapper — Outlook Classic compatibility pattern:
|
|
1936
|
+
*
|
|
1937
|
+
* <center> instructs the Word rendering engine to horizontally
|
|
1938
|
+
* centre its child block, equivalent to margin: 0 auto in CSS.
|
|
1939
|
+
*
|
|
1940
|
+
* The inner table carries the `width` HTML attribute set to the
|
|
1941
|
+
* maxWidth value. Outlook Classic reads `width` as a hard pixel
|
|
1942
|
+
* cap; it has no concept of max-width so this is the only lever
|
|
1943
|
+
* available. Modern clients receive the CSS max-width on the
|
|
1944
|
+
* same table and behave correctly.
|
|
1945
|
+
*
|
|
1946
|
+
* The outer column remains at its normal width so it always
|
|
1947
|
+
* fills its parent cell in every client — only the inner
|
|
1948
|
+
* content is capped.
|
|
1949
|
+
*/
|
|
1950
|
+
jsxRuntime.jsx("center", { children: jsxRuntime.jsx("table", { "aria-label": "Column Max Width Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, width: config.maxWidth, style: maxWidthTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: renderContent() }) }) }) }) })) : (renderContent()) }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
|
|
1866
1951
|
}
|
|
1867
1952
|
var Column_default = React.memo(Column, arePropsEqual);
|
|
1868
1953
|
|
|
@@ -1911,7 +1996,7 @@ function getBorderStyle$4(border) {
|
|
|
1911
1996
|
}
|
|
1912
1997
|
return style;
|
|
1913
1998
|
}
|
|
1914
|
-
function Container({ children, config, devMode, devNode }) {
|
|
1999
|
+
function Container({ children, config, bindings, devMode, devNode, }) {
|
|
1915
2000
|
var _a, _b, _c;
|
|
1916
2001
|
const { widthType, childrenConstraints } = config;
|
|
1917
2002
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
@@ -1929,7 +2014,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
1929
2014
|
return 0;
|
|
1930
2015
|
})();
|
|
1931
2016
|
const getChildWidths = (() => {
|
|
1932
|
-
const { widthDistributionType } = childrenConstraints;
|
|
2017
|
+
const { widthDistributionType } = childrenConstraints !== null && childrenConstraints !== void 0 ? childrenConstraints : {};
|
|
1933
2018
|
const totalGapSpace = gapWidthPx * (numChildren > 1 ? numChildren - 1 : 0);
|
|
1934
2019
|
const remainingContentSpace = containerWidthPx - totalGapSpace;
|
|
1935
2020
|
switch (widthDistributionType) {
|
|
@@ -2003,6 +2088,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2003
2088
|
width: config.gap || "0",
|
|
2004
2089
|
lineHeight: "1px",
|
|
2005
2090
|
fontSize: "1px",
|
|
2091
|
+
background: "transparent",
|
|
2006
2092
|
};
|
|
2007
2093
|
const justifyAlign = config.justifyContent
|
|
2008
2094
|
? justifyMap$2[config.justifyContent]
|
|
@@ -2023,6 +2109,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2023
2109
|
fontSize: "0",
|
|
2024
2110
|
lineHeight: "0",
|
|
2025
2111
|
height: config.gap,
|
|
2112
|
+
background: "transparent",
|
|
2026
2113
|
}, children: "\u00A0" }))] }, `child-${index}`), jsxRuntime.jsx("td", { className: isStacking ? "desktop-gap-column" : undefined, width: config.gap, style: gapTdStyle, children: "\u00A0" }, `gap-${index}`)] }, `ctn:${index}`));
|
|
2027
2114
|
}
|
|
2028
2115
|
return (jsxRuntime.jsx("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: child }, `child-${index}`));
|
|
@@ -2030,7 +2117,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2030
2117
|
return (jsxRuntime.jsx("table", { "aria-label": `Container | Table Outer`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: {
|
|
2031
2118
|
position: "relative",
|
|
2032
2119
|
...outerTableStyle,
|
|
2033
|
-
}, 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: [
|
|
2120
|
+
}, ...rootBindingProps(bindings), 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: [
|
|
2034
2121
|
widthType === "fixed" ? "container-fixed-width" : undefined,
|
|
2035
2122
|
devMode ? "main-wrapper relative" : undefined,
|
|
2036
2123
|
]
|
|
@@ -2039,22 +2126,22 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2039
2126
|
width: "100%",
|
|
2040
2127
|
maxWidth: widthType === "fixed" ? config.width || "600px" : undefined,
|
|
2041
2128
|
borderCollapse: "collapse",
|
|
2042
|
-
}, width: containerWidthAttr, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: backgroundTdStyle, children: jsxRuntime.jsx("table", { "aria-label": `Container | Border Wrapper`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: borderTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: innerTdStyle, children: jsxRuntime.jsx("table", { "aria-label": `Container | Content Table`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: contentTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: rowElements }) }) }) }) }) }) }) }) }) }), !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }), jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedFooter } })] }) }) }) }));
|
|
2129
|
+
}, width: containerWidthAttr, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: backgroundTdStyle, children: jsxRuntime.jsx("table", { "aria-label": `Container | Border Wrapper`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: borderTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: innerTdStyle, children: jsxRuntime.jsx("table", { "aria-label": `Container | Content Table`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: contentTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { ...listBindingProps(bindings), children: rowElements }) }) }) }) }) }) }) }) }) }), !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }), jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedFooter } })] }) }) }) }));
|
|
2043
2130
|
}
|
|
2044
2131
|
var Container_default = React.memo(Container, arePropsEqual);
|
|
2045
2132
|
|
|
2046
|
-
function Divider({ config, devNode }) {
|
|
2133
|
+
function Divider({ config, devNode, bindings }) {
|
|
2047
2134
|
const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", hideOnMobile, } = config;
|
|
2048
2135
|
const heightPx = parseInt(height, 10) || 1;
|
|
2049
2136
|
// Parse margin into paddingTop / paddingBottom for the outer TD.
|
|
2050
2137
|
// Outlook ignores shorthand "20px 0" on TDs — must be explicit.
|
|
2051
|
-
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw] = margin.trim().split(/\s+/);
|
|
2138
|
+
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw,] = margin.trim().split(/\s+/);
|
|
2052
2139
|
const marginTop = marginTopRaw;
|
|
2053
2140
|
const marginBottom = marginBottomRaw !== null && marginBottomRaw !== void 0 ? marginBottomRaw : marginTopRaw; // "20px 0" → top=20px, bottom=20px
|
|
2054
2141
|
// Outlook requires align on the outer TD to correctly position
|
|
2055
2142
|
// a fixed-width inner table (e.g. width="300px").
|
|
2056
2143
|
const alignAttr = align === "left" ? "left" : align === "right" ? "right" : "center";
|
|
2057
|
-
return (jsxRuntime.jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2144
|
+
return (jsxRuntime.jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2058
2145
|
position: "relative", // dev overlay anchor
|
|
2059
2146
|
width: "100%",
|
|
2060
2147
|
borderCollapse: "collapse",
|
|
@@ -2194,36 +2281,7 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2194
2281
|
mso-line-height-rule: exactly;
|
|
2195
2282
|
}
|
|
2196
2283
|
}
|
|
2197
|
-
|
|
2198
|
-
.row-content-table[data-mobile-justify="center"] { margin: 0 auto !important; float: none !important; }
|
|
2199
|
-
.row-content-table[data-mobile-justify="start"] { margin: 0 !important; float: left !important; }
|
|
2200
|
-
.row-content-table[data-mobile-justify="end"] { margin: 0 0 0 auto !important; float: right !important; }
|
|
2201
|
-
.row-content-table[data-mobile-align="center"] .child-cell { vertical-align: middle !important; }
|
|
2202
|
-
.row-content-table[data-mobile-align="start"] .child-cell { vertical-align: top !important; }
|
|
2203
|
-
.row-content-table[data-mobile-align="end"] .child-cell { vertical-align: bottom !important; }
|
|
2204
|
-
.row-content-table[data-mobile-wrap="true"] { width: 100% !important; max-width: 100% !important; }
|
|
2205
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr { display: block !important; }
|
|
2206
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell {
|
|
2207
|
-
display: block !important;
|
|
2208
|
-
width: 100% !important;
|
|
2209
|
-
box-sizing: border-box !important;
|
|
2210
|
-
}
|
|
2211
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .row-gap-td {
|
|
2212
|
-
display: none !important;
|
|
2213
|
-
width: 0 !important;
|
|
2214
|
-
height: 0 !important;
|
|
2215
|
-
}
|
|
2216
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2217
|
-
margin-bottom: 20px !important;
|
|
2218
|
-
}
|
|
2219
|
-
${["10px", "15px", "20px", "24px", "30px", "40px", ...rowGaps]
|
|
2220
|
-
.filter((gap, index, self) => self.indexOf(gap) === index)
|
|
2221
|
-
.map((gap) => `
|
|
2222
|
-
.row-content-table[data-mobile-wrap="true"][data-gap="${gap}"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2223
|
-
margin-bottom: ${gap} !important;
|
|
2224
|
-
}`)
|
|
2225
|
-
.join("\n")}
|
|
2226
|
-
}
|
|
2284
|
+
|
|
2227
2285
|
a { color: inherit; text-decoration: none; }
|
|
2228
2286
|
ol, ul { margin: 0px; padding: 0px; list-style: none; }
|
|
2229
2287
|
li {
|
|
@@ -2375,7 +2433,9 @@ function resolveAnchorStyles(anchor, fallback) {
|
|
|
2375
2433
|
else if (fallback === null || fallback === void 0 ? void 0 : fallback[prop]) {
|
|
2376
2434
|
resolved[prop] = fallback[prop];
|
|
2377
2435
|
}
|
|
2378
|
-
|
|
2436
|
+
else if (prop === "text-decoration") {
|
|
2437
|
+
resolved[prop] = "none";
|
|
2438
|
+
}
|
|
2379
2439
|
}
|
|
2380
2440
|
return Object.entries(resolved)
|
|
2381
2441
|
.map(([k, v]) => `${k}:${v}`)
|
|
@@ -2400,8 +2460,32 @@ function injectLinkStyles(html, fallback) {
|
|
|
2400
2460
|
return result;
|
|
2401
2461
|
}
|
|
2402
2462
|
|
|
2403
|
-
|
|
2404
|
-
|
|
2463
|
+
// Helper to build link href based on innerLink type
|
|
2464
|
+
function buildLinkHref$3(innerLink) {
|
|
2465
|
+
if (!innerLink || innerLink.type === "none")
|
|
2466
|
+
return null;
|
|
2467
|
+
switch (innerLink.type) {
|
|
2468
|
+
case "url":
|
|
2469
|
+
return innerLink.url || null;
|
|
2470
|
+
case "email":
|
|
2471
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
2472
|
+
case "phone":
|
|
2473
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
2474
|
+
case "anchor":
|
|
2475
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
2476
|
+
case "page_top":
|
|
2477
|
+
return "#top";
|
|
2478
|
+
case "page_bottom":
|
|
2479
|
+
return "#bottom";
|
|
2480
|
+
default:
|
|
2481
|
+
return null;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
function Heading({ config, devMode, children, bindings }) {
|
|
2485
|
+
const { text, level = "h1", padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, wordBreak, whiteSpace, innerLink, } = config;
|
|
2486
|
+
// Resolve href and target from innerLink
|
|
2487
|
+
const href = buildLinkHref$3(innerLink);
|
|
2488
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2405
2489
|
// Determine the content to render
|
|
2406
2490
|
const content = text !== null && text !== void 0 ? text : children;
|
|
2407
2491
|
const isString = typeof content === "string";
|
|
@@ -2438,12 +2522,17 @@ function Heading({ config, devMode, children }) {
|
|
|
2438
2522
|
: "";
|
|
2439
2523
|
// Dynamically create the Heading element
|
|
2440
2524
|
const HeadingTag = level;
|
|
2525
|
+
const headingElement = isString ? (jsxRuntime.jsx(HeadingTag, { style: headingStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsxRuntime.jsx(HeadingTag, { style: headingStyle, children: content }));
|
|
2441
2526
|
return (
|
|
2442
2527
|
// Wrap the heading content in a table for padding/width/background management.
|
|
2443
|
-
jsxRuntime.jsx("table", { "aria-label": "Heading Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2528
|
+
jsxRuntime.jsx("table", { "aria-label": "Heading Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2444
2529
|
width: "100%",
|
|
2445
2530
|
borderCollapse: "collapse",
|
|
2446
|
-
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: tdStyle, align: textAlign, children:
|
|
2531
|
+
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: tdStyle, align: textAlign, children: href && !devMode ? (jsxRuntime.jsx("a", { href: href, target: target, ...(target === "_blank" ? { rel: "noopener noreferrer" } : {}), style: {
|
|
2532
|
+
display: "block",
|
|
2533
|
+
textDecoration: "none",
|
|
2534
|
+
color: "inherit",
|
|
2535
|
+
}, children: headingElement })) : (headingElement) }) }) }) }));
|
|
2447
2536
|
}
|
|
2448
2537
|
var Heading_default = React.memo(Heading, arePropsEqual);
|
|
2449
2538
|
|
|
@@ -2468,7 +2557,7 @@ function Html({ children, backgroundColor = "#ffffff", }) {
|
|
|
2468
2557
|
}
|
|
2469
2558
|
|
|
2470
2559
|
// Helper to build link href based on innerLink type
|
|
2471
|
-
function buildLinkHref$
|
|
2560
|
+
function buildLinkHref$2(innerLink) {
|
|
2472
2561
|
if (!innerLink || innerLink.type === "none")
|
|
2473
2562
|
return null;
|
|
2474
2563
|
switch (innerLink.type) {
|
|
@@ -2528,11 +2617,15 @@ function getBorderStyleString$1(border) {
|
|
|
2528
2617
|
styles.push(`border-left:${border.left.width} ${border.left.style} ${border.left.color} !important;`);
|
|
2529
2618
|
return styles.join(" ");
|
|
2530
2619
|
}
|
|
2531
|
-
function Image({ config, devNode, devMode }) {
|
|
2620
|
+
function Image({ config, devNode, devMode, bindings }) {
|
|
2532
2621
|
var _a, _b;
|
|
2533
|
-
const { src, alt, innerLink, mobile } = config;
|
|
2622
|
+
const { src: originalSrc, alt, innerLink, mobile } = config;
|
|
2623
|
+
// In dev mode, if there's no src, use the placeholder
|
|
2624
|
+
const src = devMode && !originalSrc
|
|
2625
|
+
? "https://placehold.co/300x200?text=select+an+image&font=poppins"
|
|
2626
|
+
: originalSrc;
|
|
2534
2627
|
// Resolve href and target from innerLink
|
|
2535
|
-
const href = buildLinkHref$
|
|
2628
|
+
const href = buildLinkHref$2(innerLink);
|
|
2536
2629
|
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2537
2630
|
const seed = src + (alt || "");
|
|
2538
2631
|
const instanceId = seed
|
|
@@ -2546,43 +2639,37 @@ function Image({ config, devNode, devMode }) {
|
|
|
2546
2639
|
const widthAttr = desktopWidth.replace("px", "");
|
|
2547
2640
|
const heightAttr = (_a = config.height) === null || _a === void 0 ? void 0 : _a.replace("px", "");
|
|
2548
2641
|
// Determine the table's "initial" width.
|
|
2549
|
-
// If it's 300px, the table should be 300px, not 100%.
|
|
2550
2642
|
const tableWidth = isPercent ? desktopWidth : `${widthAttr}px`;
|
|
2551
|
-
//
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2643
|
+
// Calculate width attribute for Outlook
|
|
2644
|
+
let imgWidthAttr;
|
|
2645
|
+
if (config.outlookWidth) {
|
|
2646
|
+
// Use explicit outlookWidth if provided
|
|
2647
|
+
imgWidthAttr = parseInt(config.outlookWidth, 10);
|
|
2648
|
+
}
|
|
2649
|
+
else if (isPercent) {
|
|
2650
|
+
// For percentage widths, use maxWidth as fallback for Outlook
|
|
2651
|
+
const maxWidthPx = ((_b = config.maxWidth) === null || _b === void 0 ? void 0 : _b.endsWith("px"))
|
|
2652
|
+
? parseInt(config.maxWidth, 10)
|
|
2653
|
+
: undefined;
|
|
2654
|
+
imgWidthAttr = maxWidthPx !== null && maxWidthPx !== void 0 ? maxWidthPx : undefined;
|
|
2655
|
+
}
|
|
2656
|
+
else {
|
|
2657
|
+
// For fixed pixel widths, use that value
|
|
2658
|
+
imgWidthAttr = widthAttr ? parseInt(widthAttr, 10) : undefined;
|
|
2659
|
+
}
|
|
2660
|
+
// 2. Mobile Overrides
|
|
2568
2661
|
let mobileCss = "";
|
|
2569
2662
|
if (mobile) {
|
|
2570
|
-
|
|
2571
|
-
const wrapRules = [
|
|
2572
|
-
// Always reset min-width so the px lock from desktop can be overridden
|
|
2573
|
-
"min-width: 0 !important;",
|
|
2574
|
-
];
|
|
2663
|
+
const wrapRules = ["min-width: 0 !important;"];
|
|
2575
2664
|
if (mobile.width !== undefined)
|
|
2576
2665
|
wrapRules.push(`width: ${mobile.width} !important;`);
|
|
2577
2666
|
if (mobile.maxWidth !== undefined)
|
|
2578
2667
|
wrapRules.push(`max-width: ${mobile.maxWidth} !important;`);
|
|
2579
|
-
// .td-${imgClass} rules
|
|
2580
2668
|
const tdRules = [];
|
|
2581
2669
|
if (mobile.padding !== undefined)
|
|
2582
2670
|
tdRules.push(`padding: ${mobile.padding} !important;`);
|
|
2583
2671
|
if (mobile.backgroundColor !== undefined)
|
|
2584
2672
|
tdRules.push(`background-color: ${mobile.backgroundColor} !important;`);
|
|
2585
|
-
// .${imgClass} rules
|
|
2586
2673
|
const imgRules = [];
|
|
2587
2674
|
if (mobile.width !== undefined)
|
|
2588
2675
|
imgRules.push(`width: ${mobile.width} !important;`);
|
|
@@ -2605,7 +2692,6 @@ function Image({ config, devNode, devMode }) {
|
|
|
2605
2692
|
mobileCss = `
|
|
2606
2693
|
@media screen and (max-width: 768px) {
|
|
2607
2694
|
.wrap-${imgClass} {
|
|
2608
|
-
/* This breaks the px lock from desktop and makes it fluid */
|
|
2609
2695
|
${wrapRules.join("\n ")}
|
|
2610
2696
|
}
|
|
2611
2697
|
.td-${imgClass} {
|
|
@@ -2631,9 +2717,27 @@ function Image({ config, devNode, devMode }) {
|
|
|
2631
2717
|
objectPosition: config.objectPosition,
|
|
2632
2718
|
};
|
|
2633
2719
|
const imageElement = (jsxRuntime.jsx("img", { src: src, alt: alt, width: imgWidthAttr, height: heightAttr !== "auto" ? heightAttr : undefined, className: imgClass, style: imgStyle, draggable: !devMode }));
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2720
|
+
// Outlook Classic wrapper - only applied when outlookWidth is explicitly set
|
|
2721
|
+
// OR when we need to constrain a percentage-width image in Outlook
|
|
2722
|
+
const needsOutlookWrapper = config.outlookWidth || (isPercent && imgWidthAttr);
|
|
2723
|
+
const finalImageElement = needsOutlookWrapper ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("style", { dangerouslySetInnerHTML: {
|
|
2724
|
+
__html: `</style>` +
|
|
2725
|
+
`<!--[if mso]>` +
|
|
2726
|
+
`<table cellpadding="0" cellspacing="0" border="0" style="width: ${imgWidthAttr}px;">` +
|
|
2727
|
+
`<tr>` +
|
|
2728
|
+
`<td style="padding: 0; margin: 0;" width="${imgWidthAttr}">` +
|
|
2729
|
+
`<img src="${src}" alt="${alt || ""}" width="${imgWidthAttr}" height="${heightAttr !== "auto" ? heightAttr : ""}" style="display: block; width: 100%; height: auto;" />` +
|
|
2730
|
+
`</td>` +
|
|
2731
|
+
`</tr>` +
|
|
2732
|
+
`</table>` +
|
|
2733
|
+
`<![endif]-->` +
|
|
2734
|
+
`<!--[if !mso]><!-->` +
|
|
2735
|
+
`<style>`,
|
|
2736
|
+
} }), imageElement, jsxRuntime.jsx("style", { dangerouslySetInnerHTML: {
|
|
2737
|
+
__html: `</style>` + `<!--<![endif]-->` + `<style>`,
|
|
2738
|
+
} })] })) : (imageElement);
|
|
2739
|
+
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", ...rootBindingProps(bindings), style: {
|
|
2740
|
+
width: tableWidth,
|
|
2637
2741
|
maxWidth: "100%",
|
|
2638
2742
|
borderCollapse: "collapse",
|
|
2639
2743
|
margin: "0 auto",
|
|
@@ -2642,10 +2746,10 @@ function Image({ config, devNode, devMode }) {
|
|
|
2642
2746
|
backgroundColor: config.backgroundColor,
|
|
2643
2747
|
fontSize: "0",
|
|
2644
2748
|
lineHeight: "0",
|
|
2645
|
-
width: tableWidth,
|
|
2749
|
+
width: tableWidth,
|
|
2646
2750
|
}, children: href && !devMode ? (jsxRuntime.jsx("a", { href: href, target: target, ...(target === "_blank"
|
|
2647
2751
|
? { rel: "noopener noreferrer" }
|
|
2648
|
-
: {}), style: { display: "block", width: "100%" }, children:
|
|
2752
|
+
: {}), style: { display: "block", width: "100%" }, children: finalImageElement })) : (finalImageElement) }) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })] }));
|
|
2649
2753
|
}
|
|
2650
2754
|
var Image_default = React.memo(Image, arePropsEqual);
|
|
2651
2755
|
|
|
@@ -2714,12 +2818,34 @@ function getHrefFromInnerLink(innerLink) {
|
|
|
2714
2818
|
return undefined;
|
|
2715
2819
|
}
|
|
2716
2820
|
}
|
|
2717
|
-
|
|
2718
|
-
|
|
2821
|
+
/**
|
|
2822
|
+
* Resolves the width for a child <td> at the given index based on layoutColumns.
|
|
2823
|
+
*
|
|
2824
|
+
* - "equal" → equal percentage share across all children
|
|
2825
|
+
* - string[] → explicit value at the matching index (px, %, or mixed)
|
|
2826
|
+
* - undefined → undefined, so no width attribute is set (retrocompat)
|
|
2827
|
+
*/
|
|
2828
|
+
function resolveChildColumnWidth(layoutColumns, index, numChildren) {
|
|
2829
|
+
if (!layoutColumns)
|
|
2830
|
+
return undefined;
|
|
2831
|
+
if (layoutColumns === "equal")
|
|
2832
|
+
return `${100 / numChildren}%`;
|
|
2833
|
+
return layoutColumns[index];
|
|
2834
|
+
}
|
|
2835
|
+
function Row({ children, config, devNode, devMode, bindings }) {
|
|
2836
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2719
2837
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2720
2838
|
const numChildren = childrenArray.length;
|
|
2721
2839
|
const href = getHrefFromInnerLink(config.innerLink);
|
|
2722
2840
|
const target = ((_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target) || "_blank";
|
|
2841
|
+
// Whether children should stack on mobile.
|
|
2842
|
+
// Mirrors Container's isStacking pattern: drives stack-td / desktop-gap-column
|
|
2843
|
+
// / mobile-gap-spacer class names so that stacking works via non-@media CSS
|
|
2844
|
+
// rules that survive Gmail's stylesheet stripping.
|
|
2845
|
+
const isStacking = ((_b = config.mobile) === null || _b === void 0 ? void 0 : _b.wrap) === true && numChildren > 1;
|
|
2846
|
+
// Whether layoutColumns is active. When true, table-layout:fixed is applied
|
|
2847
|
+
// to the content table so Outlook Classic honours the declared column widths.
|
|
2848
|
+
const hasLayoutColumns = config.layoutColumns !== undefined;
|
|
2723
2849
|
// 1. Outer TD: Background, Border Radius, Width, Height.
|
|
2724
2850
|
const backgroundTdStyle = {
|
|
2725
2851
|
backgroundColor: config.backgroundColor,
|
|
@@ -2729,9 +2855,9 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2729
2855
|
backgroundImage: config.backgroundImage
|
|
2730
2856
|
? `url(${config.backgroundImage.src})`
|
|
2731
2857
|
: undefined,
|
|
2732
|
-
backgroundRepeat: (
|
|
2733
|
-
backgroundSize: (
|
|
2734
|
-
backgroundPosition: (
|
|
2858
|
+
backgroundRepeat: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.repeat,
|
|
2859
|
+
backgroundSize: (_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.size,
|
|
2860
|
+
backgroundPosition: (_e = config.backgroundImage) === null || _e === void 0 ? void 0 : _e.position,
|
|
2735
2861
|
...(config.borderRadius && { overflow: "hidden" }),
|
|
2736
2862
|
};
|
|
2737
2863
|
// 2. Inner Table: Border and Border Radius.
|
|
@@ -2760,24 +2886,34 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2760
2886
|
// Content table fills available space, giving Outlook Classic a hard
|
|
2761
2887
|
// boundary so text children get a constrained box and line wrapping
|
|
2762
2888
|
// triggers correctly. Use for rows containing text + image layouts.
|
|
2889
|
+
//
|
|
2890
|
+
// layoutColumns (any value) → additionally applies table-layout: fixed
|
|
2891
|
+
// so Outlook Classic honours the per-child width declarations.
|
|
2892
|
+
// Compatible with both fillWidth modes.
|
|
2763
2893
|
const contentTableStyle = {
|
|
2764
|
-
|
|
2894
|
+
// When layoutColumns is active, force 100% so Outlook Classic has a
|
|
2895
|
+
// concrete boundary to resolve percentage column widths against.
|
|
2896
|
+
// table-layout:fixed is meaningless without a fixed reference width.
|
|
2897
|
+
width: hasLayoutColumns || config.fillWidth ? "100%" : "auto",
|
|
2765
2898
|
height: "100%",
|
|
2766
2899
|
borderCollapse: "collapse",
|
|
2767
2900
|
minWidth: "1px",
|
|
2768
|
-
...(!config.fillWidth &&
|
|
2901
|
+
...(!config.fillWidth &&
|
|
2902
|
+
!hasLayoutColumns && { maxWidth: config.width || "100%" }),
|
|
2903
|
+
...(hasLayoutColumns && { tableLayout: "fixed" }),
|
|
2769
2904
|
};
|
|
2770
2905
|
// 5. Gap TD.
|
|
2771
2906
|
const gapTdStyle = {
|
|
2772
2907
|
width: config.gap || "0",
|
|
2773
2908
|
lineHeight: "1px",
|
|
2774
2909
|
fontSize: "1px",
|
|
2910
|
+
background: "transparent",
|
|
2775
2911
|
};
|
|
2776
2912
|
const tdAlign = config.justifyContent
|
|
2777
2913
|
? justifyMap$1[config.justifyContent]
|
|
2778
2914
|
: "left";
|
|
2779
2915
|
const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
|
|
2780
|
-
const content = (jsxRuntime.jsxs("table", { "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2916
|
+
const content = (jsxRuntime.jsxs("table", { "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...(!href ? rootBindingProps(bindings) : {}), style: {
|
|
2781
2917
|
position: "relative",
|
|
2782
2918
|
width: config.width || "100%",
|
|
2783
2919
|
height: config.height,
|
|
@@ -2786,15 +2922,44 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2786
2922
|
width: "100%",
|
|
2787
2923
|
height: "100%",
|
|
2788
2924
|
borderCollapse: "collapse",
|
|
2789
|
-
}, 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-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2925
|
+
}, 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-wrap": ((_f = config.mobile) === null || _f === void 0 ? void 0 : _f.wrap) ? "true" : undefined, "data-gap": config.gap, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { className: "content-tr", ...listBindingProps(bindings), children: childrenArray.map((child, index) => {
|
|
2926
|
+
// Resolve the column width for this child based on
|
|
2927
|
+
// layoutColumns. undefined when layoutColumns is not set,
|
|
2928
|
+
// preserving the original behaviour (retrocompat).
|
|
2929
|
+
const columnWidth = resolveChildColumnWidth(config.layoutColumns, index, numChildren);
|
|
2930
|
+
return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsxs("td", { align: tdAlign, ...(columnWidth && {
|
|
2931
|
+
width: columnWidth,
|
|
2932
|
+
}), style: {
|
|
2933
|
+
verticalAlign: tdValign,
|
|
2934
|
+
textAlign: tdAlign,
|
|
2935
|
+
padding: "0",
|
|
2936
|
+
margin: "0",
|
|
2937
|
+
...(columnWidth && {
|
|
2938
|
+
width: columnWidth,
|
|
2939
|
+
}),
|
|
2940
|
+
},
|
|
2941
|
+
// Mirror of Container's stack-td pattern: when isStacking,
|
|
2942
|
+
// the non-@media .stack-td rule forces display:block +
|
|
2943
|
+
// width:100% on each child, which survives Gmail's
|
|
2944
|
+
// @media stripping and achieves true mobile stacking.
|
|
2945
|
+
className: `child-cell${isStacking ? " stack-td" : ""}`, children: [child, isStacking &&
|
|
2946
|
+
index < numChildren - 1 &&
|
|
2947
|
+
config.gap && (jsxRuntime.jsx("div", { className: "mobile-gap-spacer", style: {
|
|
2948
|
+
display: "none",
|
|
2949
|
+
fontSize: "0",
|
|
2950
|
+
lineHeight: "0",
|
|
2951
|
+
height: config.gap,
|
|
2952
|
+
background: "transparent",
|
|
2953
|
+
}, children: "\u00A0" }))] }), index < numChildren - 1 &&
|
|
2954
|
+
config.gap && (jsxRuntime.jsx("td", { width: config.gap, style: gapTdStyle,
|
|
2955
|
+
// Mirror of Container's desktop-gap-column pattern:
|
|
2956
|
+
// when isStacking, the non-@media .desktop-gap-column
|
|
2957
|
+
// rule collapses the between-column gap td so it does
|
|
2958
|
+
// not create phantom space while children are stacked.
|
|
2959
|
+
className: `row-gap-td${isStacking ? " desktop-gap-column" : ""}`, children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`));
|
|
2960
|
+
}) }) }) }) }) }) }) }) }) }) }) }) }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
|
|
2796
2961
|
if (href && !devMode) {
|
|
2797
|
-
return (jsxRuntime.jsx("a", { href: href, ...({ target }), style: {
|
|
2962
|
+
return (jsxRuntime.jsx("a", { href: href, ...({ target }), ...rootBindingProps(bindings), style: {
|
|
2798
2963
|
textDecoration: "none",
|
|
2799
2964
|
color: "inherit",
|
|
2800
2965
|
display: "block",
|
|
@@ -2839,10 +3004,10 @@ function getBorderStyle$1(border) {
|
|
|
2839
3004
|
}
|
|
2840
3005
|
return style;
|
|
2841
3006
|
}
|
|
2842
|
-
const Section = ({ config, children, devNode, }) => {
|
|
3007
|
+
const Section = ({ config, children, devNode, bindings, }) => {
|
|
2843
3008
|
var _a, _b, _c;
|
|
2844
3009
|
const { sectionType, padding } = config;
|
|
2845
|
-
return (jsxRuntime.jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
3010
|
+
return (jsxRuntime.jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2846
3011
|
position: "relative",
|
|
2847
3012
|
width: "100%",
|
|
2848
3013
|
backgroundColor: config.backgroundColor,
|
|
@@ -2855,66 +3020,98 @@ const Section = ({ config, children, devNode, }) => {
|
|
|
2855
3020
|
backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
|
|
2856
3021
|
}, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: {
|
|
2857
3022
|
padding: padding,
|
|
2858
|
-
}, children: children }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
3023
|
+
}, ...listBindingProps(bindings), children: children }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: jsxRuntime.jsxs("span", { style: {
|
|
3024
|
+
backgroundColor: "black",
|
|
3025
|
+
color: "white",
|
|
3026
|
+
padding: "4px",
|
|
3027
|
+
fontSize: "14px",
|
|
3028
|
+
position: "absolute",
|
|
3029
|
+
left: 0,
|
|
3030
|
+
top: 0,
|
|
3031
|
+
}, children: ["Section | ", sectionType] }) }) }) }))] }));
|
|
2867
3032
|
};
|
|
2868
3033
|
var Section_default = React.memo(Section, arePropsEqual);
|
|
2869
3034
|
|
|
2870
|
-
function Spacer({ config, devNode }) {
|
|
2871
|
-
|
|
3035
|
+
function Spacer({ config, devNode, bindings }) {
|
|
3036
|
+
var _a, _b, _c;
|
|
3037
|
+
const { height, hideOnMobile, backgroundColor, backgroundImage } = config;
|
|
2872
3038
|
// 1. Spacer Table Style
|
|
2873
3039
|
const spacerTableStyle = {
|
|
2874
|
-
// Crucial for compatibility: Ensures no background or border interference
|
|
2875
|
-
backgroundColor: "transparent",
|
|
2876
3040
|
borderCollapse: "collapse",
|
|
2877
|
-
border: "0",
|
|
2878
3041
|
width: "100%",
|
|
2879
|
-
// Note the CSS standard dash convention: 'mso-table-lspace'
|
|
2880
|
-
// ["mso-table-lspace" as string]: "0pt",
|
|
2881
|
-
["msoTableLspace"]: "0pt",
|
|
2882
|
-
// ["mso-table-rspace" as string]: "0pt",
|
|
2883
|
-
["msoTableRspace"]: "0pt",
|
|
2884
3042
|
};
|
|
2885
3043
|
// 2. Spacer TD Style: The element that creates the actual vertical space
|
|
2886
3044
|
const spacerTdStyle = {
|
|
2887
3045
|
height: height,
|
|
2888
|
-
|
|
3046
|
+
maxHeight: height,
|
|
2889
3047
|
fontSize: "0",
|
|
2890
3048
|
lineHeight: "0",
|
|
2891
3049
|
padding: "0",
|
|
3050
|
+
margin: "0",
|
|
3051
|
+
border: "none",
|
|
3052
|
+
color: "transparent",
|
|
3053
|
+
// Background applied at TD level for Outlook Classic compatibility
|
|
3054
|
+
...(backgroundColor && { backgroundColor }),
|
|
3055
|
+
...(backgroundImage && {
|
|
3056
|
+
backgroundImage: `url(${backgroundImage.src})`,
|
|
3057
|
+
backgroundRepeat: (_a = backgroundImage.repeat) !== null && _a !== void 0 ? _a : "no-repeat",
|
|
3058
|
+
backgroundSize: (_b = backgroundImage.size) !== null && _b !== void 0 ? _b : "cover",
|
|
3059
|
+
backgroundPosition: (_c = backgroundImage.position) !== null && _c !== void 0 ? _c : "center",
|
|
3060
|
+
}),
|
|
2892
3061
|
};
|
|
2893
3062
|
// Parse height for the HTML attribute
|
|
2894
3063
|
const spacerHeightAttribute = parseInt(height, 10) || 1;
|
|
2895
|
-
return (
|
|
2896
|
-
// Outer table ensures the spacer spans the full width of its container
|
|
2897
|
-
jsxRuntime.jsxs("table", { "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
3064
|
+
return (jsxRuntime.jsxs("table", { "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2898
3065
|
// --- Start dev
|
|
2899
3066
|
position: "relative",
|
|
2900
3067
|
// --- End dev
|
|
2901
3068
|
...spacerTableStyle,
|
|
2902
|
-
}, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle,
|
|
2903
|
-
|
|
2904
|
-
|
|
3069
|
+
}, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: spacerTdStyle, height: spacerHeightAttribute, ...(backgroundColor && !backgroundImage
|
|
3070
|
+
? { bgcolor: backgroundColor }
|
|
3071
|
+
: {}) }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
|
|
2905
3072
|
}
|
|
2906
3073
|
var Spacer_default = React.memo(Spacer, arePropsEqual);
|
|
2907
3074
|
|
|
2908
|
-
|
|
2909
|
-
|
|
3075
|
+
// Helper to build link href based on innerLink type
|
|
3076
|
+
function buildLinkHref$1(innerLink) {
|
|
3077
|
+
if (!innerLink || innerLink.type === "none")
|
|
3078
|
+
return null;
|
|
3079
|
+
switch (innerLink.type) {
|
|
3080
|
+
case "url":
|
|
3081
|
+
return innerLink.url || null;
|
|
3082
|
+
case "email":
|
|
3083
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
3084
|
+
case "phone":
|
|
3085
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
3086
|
+
case "anchor":
|
|
3087
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
3088
|
+
case "page_top":
|
|
3089
|
+
return "#top";
|
|
3090
|
+
case "page_bottom":
|
|
3091
|
+
return "#bottom";
|
|
3092
|
+
default:
|
|
3093
|
+
return null;
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
function Text({ config, devMode, children, bindings }) {
|
|
3097
|
+
const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth, innerLink, } = config;
|
|
3098
|
+
// Resolve href and target from innerLink
|
|
3099
|
+
const href = buildLinkHref$1(innerLink);
|
|
3100
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2910
3101
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
3102
|
+
// When maxWidth is set, this TD stays at width: 100% so it always fills
|
|
3103
|
+
// its parent — the inner maxWidth table (see below) does the actual
|
|
3104
|
+
// capping, keeping the outer layout intact in all clients.
|
|
2911
3105
|
const tdStyle = {
|
|
2912
3106
|
padding: padding,
|
|
2913
3107
|
backgroundColor: backgroundColor,
|
|
2914
3108
|
width: "100%",
|
|
2915
3109
|
verticalAlign: "top",
|
|
2916
3110
|
};
|
|
2917
|
-
// 2. Content Style: Applied directly to
|
|
3111
|
+
// 2. Content Style: Applied directly to the inner div wrapper.
|
|
3112
|
+
// maxWidth is intentionally omitted here — putting it on a div has no
|
|
3113
|
+
// effect in Outlook Classic (Word engine ignores CSS on div elements).
|
|
3114
|
+
// The constraint is enforced at the table level instead (see below).
|
|
2918
3115
|
const contentStyle = {
|
|
2919
3116
|
color: color,
|
|
2920
3117
|
textAlign: textAlign,
|
|
@@ -2933,7 +3130,18 @@ function Text({ config, devMode, children }) {
|
|
|
2933
3130
|
wordBreak: wordBreak,
|
|
2934
3131
|
margin: "0",
|
|
2935
3132
|
padding: "0",
|
|
2936
|
-
|
|
3133
|
+
};
|
|
3134
|
+
// 3. maxWidth constraining table style (modern clients).
|
|
3135
|
+
// The `width` HTML attribute on this table is what Outlook Classic
|
|
3136
|
+
// (Word engine) reads — it has no concept of max-width, but it does
|
|
3137
|
+
// honour the `width` attribute as a hard column cap.
|
|
3138
|
+
// The CSS max-width here handles modern web/email clients correctly.
|
|
3139
|
+
// <center> around it ensures the constrained block stays horizontally
|
|
3140
|
+
// centred in both the Word engine and standards-based renderers.
|
|
3141
|
+
const maxWidthTableStyle = {
|
|
3142
|
+
width: "100%",
|
|
3143
|
+
maxWidth: maxWidth,
|
|
3144
|
+
borderCollapse: "collapse",
|
|
2937
3145
|
};
|
|
2938
3146
|
// Determine content to render
|
|
2939
3147
|
const content = text !== null && text !== void 0 ? text : children;
|
|
@@ -2941,10 +3149,32 @@ function Text({ config, devMode, children }) {
|
|
|
2941
3149
|
const processedHtml = isString
|
|
2942
3150
|
? injectLinkStyles(content, contentStyle)
|
|
2943
3151
|
: "";
|
|
2944
|
-
|
|
3152
|
+
const innerContent = isString ? (jsxRuntime.jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsxRuntime.jsx("div", { style: contentStyle, children: content }));
|
|
3153
|
+
const wrappedContent = maxWidth ? (
|
|
3154
|
+
/*
|
|
3155
|
+
* maxWidth wrapper — Outlook Classic compatibility pattern:
|
|
3156
|
+
*
|
|
3157
|
+
* <center> instructs the Word rendering engine to horizontally
|
|
3158
|
+
* centre its child block, equivalent to margin: 0 auto in CSS.
|
|
3159
|
+
*
|
|
3160
|
+
* The inner table carries the `width` HTML attribute set to the
|
|
3161
|
+
* maxWidth value. Outlook Classic reads `width` as a hard pixel
|
|
3162
|
+
* cap; it has no concept of max-width so this is the only lever
|
|
3163
|
+
* available. Modern clients receive the CSS max-width on the
|
|
3164
|
+
* same table and behave correctly.
|
|
3165
|
+
*
|
|
3166
|
+
* The outer TD remains at width: 100% so it always fills its
|
|
3167
|
+
* parent cell in every client — only the inner content is capped.
|
|
3168
|
+
*/
|
|
3169
|
+
jsxRuntime.jsx("center", { children: jsxRuntime.jsx("table", { "aria-label": "Text Max Width Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, width: maxWidth, style: maxWidthTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: innerContent }) }) }) }) })) : (innerContent);
|
|
3170
|
+
return (jsxRuntime.jsx("table", { "aria-label": "Text Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2945
3171
|
width: "100%",
|
|
2946
3172
|
borderCollapse: "collapse",
|
|
2947
|
-
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: tdStyle, align: textAlign, children:
|
|
3173
|
+
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: tdStyle, align: textAlign, children: href && !devMode ? (jsxRuntime.jsx("a", { href: href, target: target, ...(target === "_blank" ? { rel: "noopener noreferrer" } : {}), style: {
|
|
3174
|
+
display: "block",
|
|
3175
|
+
textDecoration: "none",
|
|
3176
|
+
color: "inherit",
|
|
3177
|
+
}, children: wrappedContent })) : (wrappedContent) }) }) }) }));
|
|
2948
3178
|
}
|
|
2949
3179
|
var Text_default = React.memo(Text, arePropsEqual);
|
|
2950
3180
|
|
|
@@ -3070,7 +3300,7 @@ function buildLinkHref(innerLink) {
|
|
|
3070
3300
|
return null;
|
|
3071
3301
|
}
|
|
3072
3302
|
}
|
|
3073
|
-
function Icon({ config, devNode, devMode, children }) {
|
|
3303
|
+
function Icon({ config, devNode, devMode, children, bindings }) {
|
|
3074
3304
|
const {
|
|
3075
3305
|
// base64Source,
|
|
3076
3306
|
width, height, backgroundColor, padding = "0", borderRadius = "0", border, innerLink, justifyContent = "center", } = config;
|
|
@@ -3205,7 +3435,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
3205
3435
|
<!--<![endif]-->
|
|
3206
3436
|
`
|
|
3207
3437
|
: null;
|
|
3208
|
-
return (jsxRuntime.jsxs("table", { "aria-label": "Icon", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, style: {
|
|
3438
|
+
return (jsxRuntime.jsxs("table", { "aria-label": "Icon", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, ...rootBindingProps(bindings), style: {
|
|
3209
3439
|
// --- Start dev
|
|
3210
3440
|
position: "relative",
|
|
3211
3441
|
// --- End dev
|