@pagenflow/email 1.4.7 → 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 +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/linearizeStyle.d.ts +10 -0
- package/dist/index.cjs.js +302 -133
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +302 -133
- 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",
|
|
@@ -1787,7 +1838,7 @@ function getBorderStyle$5(border) {
|
|
|
1787
1838
|
}
|
|
1788
1839
|
return style;
|
|
1789
1840
|
}
|
|
1790
|
-
function Column({ children, config, devNode }) {
|
|
1841
|
+
function Column({ children, config, devNode, bindings }) {
|
|
1791
1842
|
var _a, _b, _c;
|
|
1792
1843
|
// Process children array for gap support
|
|
1793
1844
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
@@ -1839,6 +1890,7 @@ function Column({ children, config, devNode }) {
|
|
|
1839
1890
|
// treat it as content-box height and add padding on top, causing the
|
|
1840
1891
|
// total to exceed the declared height in preview mode.
|
|
1841
1892
|
verticalAlign: config.alignItems ? alignMap$2[config.alignItems] : "top",
|
|
1893
|
+
background: "transparent",
|
|
1842
1894
|
};
|
|
1843
1895
|
// 4. Gap spacer style (used between children)
|
|
1844
1896
|
const gapSpacerStyle = {
|
|
@@ -1846,6 +1898,7 @@ function Column({ children, config, devNode }) {
|
|
|
1846
1898
|
lineHeight: "1px",
|
|
1847
1899
|
fontSize: "1px",
|
|
1848
1900
|
width: "100%",
|
|
1901
|
+
background: "transparent",
|
|
1849
1902
|
};
|
|
1850
1903
|
// 5. maxWidth constraining table style (modern clients).
|
|
1851
1904
|
// The `width` HTML attribute on this table is what Outlook Classic
|
|
@@ -1860,10 +1913,10 @@ function Column({ children, config, devNode }) {
|
|
|
1860
1913
|
borderCollapse: "collapse",
|
|
1861
1914
|
};
|
|
1862
1915
|
// 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",
|
|
1916
|
+
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
1917
|
width: "100%",
|
|
1865
1918
|
borderCollapse: "collapse",
|
|
1866
|
-
}, children: jsx("tbody", { children: childrenArray.map((child, index) => (jsxs(Fragment, { children: [jsx("tr", { children: jsx("td", { style: {
|
|
1919
|
+
}, children: jsx("tbody", { ...listBindingProps(bindings), children: childrenArray.map((child, index) => (jsxs(Fragment, { children: [jsx("tr", { children: jsx("td", { style: {
|
|
1867
1920
|
verticalAlign: config.alignItems
|
|
1868
1921
|
? alignMap$2[config.alignItems]
|
|
1869
1922
|
: "top",
|
|
@@ -1872,7 +1925,7 @@ function Column({ children, config, devNode }) {
|
|
|
1872
1925
|
: "top", align: config.alignItems
|
|
1873
1926
|
? alignMap$2[config.alignItems]
|
|
1874
1927
|
: "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: {
|
|
1928
|
+
return (jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
1876
1929
|
position: "relative",
|
|
1877
1930
|
...outerTableStyle,
|
|
1878
1931
|
}, ...(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 +1994,7 @@ function getBorderStyle$4(border) {
|
|
|
1941
1994
|
}
|
|
1942
1995
|
return style;
|
|
1943
1996
|
}
|
|
1944
|
-
function Container({ children, config, devMode, devNode }) {
|
|
1997
|
+
function Container({ children, config, bindings, devMode, devNode, }) {
|
|
1945
1998
|
var _a, _b, _c;
|
|
1946
1999
|
const { widthType, childrenConstraints } = config;
|
|
1947
2000
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
@@ -1959,7 +2012,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
1959
2012
|
return 0;
|
|
1960
2013
|
})();
|
|
1961
2014
|
const getChildWidths = (() => {
|
|
1962
|
-
const { widthDistributionType } = childrenConstraints;
|
|
2015
|
+
const { widthDistributionType } = childrenConstraints !== null && childrenConstraints !== void 0 ? childrenConstraints : {};
|
|
1963
2016
|
const totalGapSpace = gapWidthPx * (numChildren > 1 ? numChildren - 1 : 0);
|
|
1964
2017
|
const remainingContentSpace = containerWidthPx - totalGapSpace;
|
|
1965
2018
|
switch (widthDistributionType) {
|
|
@@ -2033,6 +2086,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2033
2086
|
width: config.gap || "0",
|
|
2034
2087
|
lineHeight: "1px",
|
|
2035
2088
|
fontSize: "1px",
|
|
2089
|
+
background: "transparent",
|
|
2036
2090
|
};
|
|
2037
2091
|
const justifyAlign = config.justifyContent
|
|
2038
2092
|
? justifyMap$2[config.justifyContent]
|
|
@@ -2053,6 +2107,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2053
2107
|
fontSize: "0",
|
|
2054
2108
|
lineHeight: "0",
|
|
2055
2109
|
height: config.gap,
|
|
2110
|
+
background: "transparent",
|
|
2056
2111
|
}, children: "\u00A0" }))] }, `child-${index}`), jsx("td", { className: isStacking ? "desktop-gap-column" : undefined, width: config.gap, style: gapTdStyle, children: "\u00A0" }, `gap-${index}`)] }, `ctn:${index}`));
|
|
2057
2112
|
}
|
|
2058
2113
|
return (jsx("td", { className: isStacking ? "stack-td" : undefined, width: getChildWidths[index], style: childTdStyle, children: child }, `child-${index}`));
|
|
@@ -2060,7 +2115,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2060
2115
|
return (jsx("table", { "aria-label": `Container | Table Outer`, cellPadding: 0, cellSpacing: 0, role: "presentation", border: 0, style: {
|
|
2061
2116
|
position: "relative",
|
|
2062
2117
|
...outerTableStyle,
|
|
2063
|
-
}, children: jsx("tbody", { children: jsx("tr", { children: jsxs("td", { align: justifyAlign, children: [jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedWrapper } }), jsxs("table", { className: [
|
|
2118
|
+
}, ...rootBindingProps(bindings), children: jsx("tbody", { children: jsx("tr", { children: jsxs("td", { align: justifyAlign, children: [jsx("div", { dangerouslySetInnerHTML: { __html: msoFixedWrapper } }), jsxs("table", { className: [
|
|
2064
2119
|
widthType === "fixed" ? "container-fixed-width" : undefined,
|
|
2065
2120
|
devMode ? "main-wrapper relative" : undefined,
|
|
2066
2121
|
]
|
|
@@ -2069,22 +2124,22 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
2069
2124
|
width: "100%",
|
|
2070
2125
|
maxWidth: widthType === "fixed" ? config.width || "600px" : undefined,
|
|
2071
2126
|
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 } })] }) }) }) }));
|
|
2127
|
+
}, 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
2128
|
}
|
|
2074
2129
|
var Container_default = memo(Container, arePropsEqual);
|
|
2075
2130
|
|
|
2076
|
-
function Divider({ config, devNode }) {
|
|
2131
|
+
function Divider({ config, devNode, bindings }) {
|
|
2077
2132
|
const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", hideOnMobile, } = config;
|
|
2078
2133
|
const heightPx = parseInt(height, 10) || 1;
|
|
2079
2134
|
// Parse margin into paddingTop / paddingBottom for the outer TD.
|
|
2080
2135
|
// Outlook ignores shorthand "20px 0" on TDs — must be explicit.
|
|
2081
|
-
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw] = margin.trim().split(/\s+/);
|
|
2136
|
+
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw,] = margin.trim().split(/\s+/);
|
|
2082
2137
|
const marginTop = marginTopRaw;
|
|
2083
2138
|
const marginBottom = marginBottomRaw !== null && marginBottomRaw !== void 0 ? marginBottomRaw : marginTopRaw; // "20px 0" → top=20px, bottom=20px
|
|
2084
2139
|
// Outlook requires align on the outer TD to correctly position
|
|
2085
2140
|
// a fixed-width inner table (e.g. width="300px").
|
|
2086
2141
|
const alignAttr = align === "left" ? "left" : align === "right" ? "right" : "center";
|
|
2087
|
-
return (jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2142
|
+
return (jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2088
2143
|
position: "relative", // dev overlay anchor
|
|
2089
2144
|
width: "100%",
|
|
2090
2145
|
borderCollapse: "collapse",
|
|
@@ -2403,8 +2458,32 @@ function injectLinkStyles(html, fallback) {
|
|
|
2403
2458
|
return result;
|
|
2404
2459
|
}
|
|
2405
2460
|
|
|
2406
|
-
|
|
2407
|
-
|
|
2461
|
+
// Helper to build link href based on innerLink type
|
|
2462
|
+
function buildLinkHref$3(innerLink) {
|
|
2463
|
+
if (!innerLink || innerLink.type === "none")
|
|
2464
|
+
return null;
|
|
2465
|
+
switch (innerLink.type) {
|
|
2466
|
+
case "url":
|
|
2467
|
+
return innerLink.url || null;
|
|
2468
|
+
case "email":
|
|
2469
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
2470
|
+
case "phone":
|
|
2471
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
2472
|
+
case "anchor":
|
|
2473
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
2474
|
+
case "page_top":
|
|
2475
|
+
return "#top";
|
|
2476
|
+
case "page_bottom":
|
|
2477
|
+
return "#bottom";
|
|
2478
|
+
default:
|
|
2479
|
+
return null;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
function Heading({ config, devMode, children, bindings }) {
|
|
2483
|
+
const { text, level = "h1", padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, wordBreak, whiteSpace, innerLink, } = config;
|
|
2484
|
+
// Resolve href and target from innerLink
|
|
2485
|
+
const href = buildLinkHref$3(innerLink);
|
|
2486
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2408
2487
|
// Determine the content to render
|
|
2409
2488
|
const content = text !== null && text !== void 0 ? text : children;
|
|
2410
2489
|
const isString = typeof content === "string";
|
|
@@ -2441,12 +2520,17 @@ function Heading({ config, devMode, children }) {
|
|
|
2441
2520
|
: "";
|
|
2442
2521
|
// Dynamically create the Heading element
|
|
2443
2522
|
const HeadingTag = level;
|
|
2523
|
+
const headingElement = isString ? (jsx(HeadingTag, { style: headingStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsx(HeadingTag, { style: headingStyle, children: content }));
|
|
2444
2524
|
return (
|
|
2445
2525
|
// 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: {
|
|
2526
|
+
jsx("table", { "aria-label": "Heading Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2447
2527
|
width: "100%",
|
|
2448
2528
|
borderCollapse: "collapse",
|
|
2449
|
-
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children:
|
|
2529
|
+
}, 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: {
|
|
2530
|
+
display: "block",
|
|
2531
|
+
textDecoration: "none",
|
|
2532
|
+
color: "inherit",
|
|
2533
|
+
}, children: headingElement })) : (headingElement) }) }) }) }));
|
|
2450
2534
|
}
|
|
2451
2535
|
var Heading_default = memo(Heading, arePropsEqual);
|
|
2452
2536
|
|
|
@@ -2471,7 +2555,7 @@ function Html({ children, backgroundColor = "#ffffff", }) {
|
|
|
2471
2555
|
}
|
|
2472
2556
|
|
|
2473
2557
|
// Helper to build link href based on innerLink type
|
|
2474
|
-
function buildLinkHref$
|
|
2558
|
+
function buildLinkHref$2(innerLink) {
|
|
2475
2559
|
if (!innerLink || innerLink.type === "none")
|
|
2476
2560
|
return null;
|
|
2477
2561
|
switch (innerLink.type) {
|
|
@@ -2531,11 +2615,15 @@ function getBorderStyleString$1(border) {
|
|
|
2531
2615
|
styles.push(`border-left:${border.left.width} ${border.left.style} ${border.left.color} !important;`);
|
|
2532
2616
|
return styles.join(" ");
|
|
2533
2617
|
}
|
|
2534
|
-
function Image({ config, devNode, devMode }) {
|
|
2618
|
+
function Image({ config, devNode, devMode, bindings }) {
|
|
2535
2619
|
var _a, _b;
|
|
2536
|
-
const { src, alt, innerLink, mobile } = config;
|
|
2620
|
+
const { src: originalSrc, alt, innerLink, mobile } = config;
|
|
2621
|
+
// In dev mode, if there's no src, use the placeholder
|
|
2622
|
+
const src = devMode && !originalSrc
|
|
2623
|
+
? "https://placehold.co/300x200?text=select+an+image&font=poppins"
|
|
2624
|
+
: originalSrc;
|
|
2537
2625
|
// Resolve href and target from innerLink
|
|
2538
|
-
const href = buildLinkHref$
|
|
2626
|
+
const href = buildLinkHref$2(innerLink);
|
|
2539
2627
|
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2540
2628
|
const seed = src + (alt || "");
|
|
2541
2629
|
const instanceId = seed
|
|
@@ -2549,43 +2637,37 @@ function Image({ config, devNode, devMode }) {
|
|
|
2549
2637
|
const widthAttr = desktopWidth.replace("px", "");
|
|
2550
2638
|
const heightAttr = (_a = config.height) === null || _a === void 0 ? void 0 : _a.replace("px", "");
|
|
2551
2639
|
// Determine the table's "initial" width.
|
|
2552
|
-
// If it's 300px, the table should be 300px, not 100%.
|
|
2553
2640
|
const tableWidth = isPercent ? desktopWidth : `${widthAttr}px`;
|
|
2554
|
-
//
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2641
|
+
// Calculate width attribute for Outlook
|
|
2642
|
+
let imgWidthAttr;
|
|
2643
|
+
if (config.outlookWidth) {
|
|
2644
|
+
// Use explicit outlookWidth if provided
|
|
2645
|
+
imgWidthAttr = parseInt(config.outlookWidth, 10);
|
|
2646
|
+
}
|
|
2647
|
+
else if (isPercent) {
|
|
2648
|
+
// For percentage widths, use maxWidth as fallback for Outlook
|
|
2649
|
+
const maxWidthPx = ((_b = config.maxWidth) === null || _b === void 0 ? void 0 : _b.endsWith("px"))
|
|
2650
|
+
? parseInt(config.maxWidth, 10)
|
|
2651
|
+
: undefined;
|
|
2652
|
+
imgWidthAttr = maxWidthPx !== null && maxWidthPx !== void 0 ? maxWidthPx : undefined;
|
|
2653
|
+
}
|
|
2654
|
+
else {
|
|
2655
|
+
// For fixed pixel widths, use that value
|
|
2656
|
+
imgWidthAttr = widthAttr ? parseInt(widthAttr, 10) : undefined;
|
|
2657
|
+
}
|
|
2658
|
+
// 2. Mobile Overrides
|
|
2571
2659
|
let mobileCss = "";
|
|
2572
2660
|
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
|
-
];
|
|
2661
|
+
const wrapRules = ["min-width: 0 !important;"];
|
|
2578
2662
|
if (mobile.width !== undefined)
|
|
2579
2663
|
wrapRules.push(`width: ${mobile.width} !important;`);
|
|
2580
2664
|
if (mobile.maxWidth !== undefined)
|
|
2581
2665
|
wrapRules.push(`max-width: ${mobile.maxWidth} !important;`);
|
|
2582
|
-
// .td-${imgClass} rules
|
|
2583
2666
|
const tdRules = [];
|
|
2584
2667
|
if (mobile.padding !== undefined)
|
|
2585
2668
|
tdRules.push(`padding: ${mobile.padding} !important;`);
|
|
2586
2669
|
if (mobile.backgroundColor !== undefined)
|
|
2587
2670
|
tdRules.push(`background-color: ${mobile.backgroundColor} !important;`);
|
|
2588
|
-
// .${imgClass} rules
|
|
2589
2671
|
const imgRules = [];
|
|
2590
2672
|
if (mobile.width !== undefined)
|
|
2591
2673
|
imgRules.push(`width: ${mobile.width} !important;`);
|
|
@@ -2608,7 +2690,6 @@ function Image({ config, devNode, devMode }) {
|
|
|
2608
2690
|
mobileCss = `
|
|
2609
2691
|
@media screen and (max-width: 768px) {
|
|
2610
2692
|
.wrap-${imgClass} {
|
|
2611
|
-
/* This breaks the px lock from desktop and makes it fluid */
|
|
2612
2693
|
${wrapRules.join("\n ")}
|
|
2613
2694
|
}
|
|
2614
2695
|
.td-${imgClass} {
|
|
@@ -2634,9 +2715,27 @@ function Image({ config, devNode, devMode }) {
|
|
|
2634
2715
|
objectPosition: config.objectPosition,
|
|
2635
2716
|
};
|
|
2636
2717
|
const imageElement = (jsx("img", { src: src, alt: alt, width: imgWidthAttr, height: heightAttr !== "auto" ? heightAttr : undefined, className: imgClass, style: imgStyle, draggable: !devMode }));
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2718
|
+
// Outlook Classic wrapper - only applied when outlookWidth is explicitly set
|
|
2719
|
+
// OR when we need to constrain a percentage-width image in Outlook
|
|
2720
|
+
const needsOutlookWrapper = config.outlookWidth || (isPercent && imgWidthAttr);
|
|
2721
|
+
const finalImageElement = needsOutlookWrapper ? (jsxs(Fragment$1, { children: [jsx("style", { dangerouslySetInnerHTML: {
|
|
2722
|
+
__html: `</style>` +
|
|
2723
|
+
`<!--[if mso]>` +
|
|
2724
|
+
`<table cellpadding="0" cellspacing="0" border="0" style="width: ${imgWidthAttr}px;">` +
|
|
2725
|
+
`<tr>` +
|
|
2726
|
+
`<td style="padding: 0; margin: 0;" width="${imgWidthAttr}">` +
|
|
2727
|
+
`<img src="${src}" alt="${alt || ""}" width="${imgWidthAttr}" height="${heightAttr !== "auto" ? heightAttr : ""}" style="display: block; width: 100%; height: auto;" />` +
|
|
2728
|
+
`</td>` +
|
|
2729
|
+
`</tr>` +
|
|
2730
|
+
`</table>` +
|
|
2731
|
+
`<![endif]-->` +
|
|
2732
|
+
`<!--[if !mso]><!-->` +
|
|
2733
|
+
`<style>`,
|
|
2734
|
+
} }), imageElement, jsx("style", { dangerouslySetInnerHTML: {
|
|
2735
|
+
__html: `</style>` + `<!--<![endif]-->` + `<style>`,
|
|
2736
|
+
} })] })) : (imageElement);
|
|
2737
|
+
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: {
|
|
2738
|
+
width: tableWidth,
|
|
2640
2739
|
maxWidth: "100%",
|
|
2641
2740
|
borderCollapse: "collapse",
|
|
2642
2741
|
margin: "0 auto",
|
|
@@ -2645,10 +2744,10 @@ function Image({ config, devNode, devMode }) {
|
|
|
2645
2744
|
backgroundColor: config.backgroundColor,
|
|
2646
2745
|
fontSize: "0",
|
|
2647
2746
|
lineHeight: "0",
|
|
2648
|
-
width: tableWidth,
|
|
2747
|
+
width: tableWidth,
|
|
2649
2748
|
}, children: href && !devMode ? (jsx("a", { href: href, target: target, ...(target === "_blank"
|
|
2650
2749
|
? { rel: "noopener noreferrer" }
|
|
2651
|
-
: {}), style: { display: "block", width: "100%" }, children:
|
|
2750
|
+
: {}), style: { display: "block", width: "100%" }, children: finalImageElement })) : (finalImageElement) }) }) }), devMode && !!devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] })] }));
|
|
2652
2751
|
}
|
|
2653
2752
|
var Image_default = memo(Image, arePropsEqual);
|
|
2654
2753
|
|
|
@@ -2717,7 +2816,21 @@ function getHrefFromInnerLink(innerLink) {
|
|
|
2717
2816
|
return undefined;
|
|
2718
2817
|
}
|
|
2719
2818
|
}
|
|
2720
|
-
|
|
2819
|
+
/**
|
|
2820
|
+
* Resolves the width for a child <td> at the given index based on layoutColumns.
|
|
2821
|
+
*
|
|
2822
|
+
* - "equal" → equal percentage share across all children
|
|
2823
|
+
* - string[] → explicit value at the matching index (px, %, or mixed)
|
|
2824
|
+
* - undefined → undefined, so no width attribute is set (retrocompat)
|
|
2825
|
+
*/
|
|
2826
|
+
function resolveChildColumnWidth(layoutColumns, index, numChildren) {
|
|
2827
|
+
if (!layoutColumns)
|
|
2828
|
+
return undefined;
|
|
2829
|
+
if (layoutColumns === "equal")
|
|
2830
|
+
return `${100 / numChildren}%`;
|
|
2831
|
+
return layoutColumns[index];
|
|
2832
|
+
}
|
|
2833
|
+
function Row({ children, config, devNode, devMode, bindings }) {
|
|
2721
2834
|
var _a, _b, _c, _d, _e, _f;
|
|
2722
2835
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2723
2836
|
const numChildren = childrenArray.length;
|
|
@@ -2728,6 +2841,9 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2728
2841
|
// / mobile-gap-spacer class names so that stacking works via non-@media CSS
|
|
2729
2842
|
// rules that survive Gmail's stylesheet stripping.
|
|
2730
2843
|
const isStacking = ((_b = config.mobile) === null || _b === void 0 ? void 0 : _b.wrap) === true && numChildren > 1;
|
|
2844
|
+
// Whether layoutColumns is active. When true, table-layout:fixed is applied
|
|
2845
|
+
// to the content table so Outlook Classic honours the declared column widths.
|
|
2846
|
+
const hasLayoutColumns = config.layoutColumns !== undefined;
|
|
2731
2847
|
// 1. Outer TD: Background, Border Radius, Width, Height.
|
|
2732
2848
|
const backgroundTdStyle = {
|
|
2733
2849
|
backgroundColor: config.backgroundColor,
|
|
@@ -2768,24 +2884,34 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2768
2884
|
// Content table fills available space, giving Outlook Classic a hard
|
|
2769
2885
|
// boundary so text children get a constrained box and line wrapping
|
|
2770
2886
|
// triggers correctly. Use for rows containing text + image layouts.
|
|
2887
|
+
//
|
|
2888
|
+
// layoutColumns (any value) → additionally applies table-layout: fixed
|
|
2889
|
+
// so Outlook Classic honours the per-child width declarations.
|
|
2890
|
+
// Compatible with both fillWidth modes.
|
|
2771
2891
|
const contentTableStyle = {
|
|
2772
|
-
|
|
2892
|
+
// When layoutColumns is active, force 100% so Outlook Classic has a
|
|
2893
|
+
// concrete boundary to resolve percentage column widths against.
|
|
2894
|
+
// table-layout:fixed is meaningless without a fixed reference width.
|
|
2895
|
+
width: hasLayoutColumns || config.fillWidth ? "100%" : "auto",
|
|
2773
2896
|
height: "100%",
|
|
2774
2897
|
borderCollapse: "collapse",
|
|
2775
2898
|
minWidth: "1px",
|
|
2776
|
-
...(!config.fillWidth &&
|
|
2899
|
+
...(!config.fillWidth &&
|
|
2900
|
+
!hasLayoutColumns && { maxWidth: config.width || "100%" }),
|
|
2901
|
+
...(hasLayoutColumns && { tableLayout: "fixed" }),
|
|
2777
2902
|
};
|
|
2778
2903
|
// 5. Gap TD.
|
|
2779
2904
|
const gapTdStyle = {
|
|
2780
2905
|
width: config.gap || "0",
|
|
2781
2906
|
lineHeight: "1px",
|
|
2782
2907
|
fontSize: "1px",
|
|
2908
|
+
background: "transparent",
|
|
2783
2909
|
};
|
|
2784
2910
|
const tdAlign = config.justifyContent
|
|
2785
2911
|
? justifyMap$1[config.justifyContent]
|
|
2786
2912
|
: "left";
|
|
2787
2913
|
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: {
|
|
2914
|
+
const content = (jsxs("table", { "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...(!href ? rootBindingProps(bindings) : {}), style: {
|
|
2789
2915
|
position: "relative",
|
|
2790
2916
|
width: config.width || "100%",
|
|
2791
2917
|
height: config.height,
|
|
@@ -2794,32 +2920,44 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2794
2920
|
width: "100%",
|
|
2795
2921
|
height: "100%",
|
|
2796
2922
|
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
|
-
|
|
2923
|
+
}, 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) => {
|
|
2924
|
+
// Resolve the column width for this child based on
|
|
2925
|
+
// layoutColumns. undefined when layoutColumns is not set,
|
|
2926
|
+
// preserving the original behaviour (retrocompat).
|
|
2927
|
+
const columnWidth = resolveChildColumnWidth(config.layoutColumns, index, numChildren);
|
|
2928
|
+
return (jsxs(Fragment, { children: [jsxs("td", { align: tdAlign, ...(columnWidth && {
|
|
2929
|
+
width: columnWidth,
|
|
2930
|
+
}), style: {
|
|
2931
|
+
verticalAlign: tdValign,
|
|
2932
|
+
textAlign: tdAlign,
|
|
2933
|
+
padding: "0",
|
|
2934
|
+
margin: "0",
|
|
2935
|
+
...(columnWidth && {
|
|
2936
|
+
width: columnWidth,
|
|
2937
|
+
}),
|
|
2938
|
+
},
|
|
2939
|
+
// Mirror of Container's stack-td pattern: when isStacking,
|
|
2940
|
+
// the non-@media .stack-td rule forces display:block +
|
|
2941
|
+
// width:100% on each child, which survives Gmail's
|
|
2942
|
+
// @media stripping and achieves true mobile stacking.
|
|
2943
|
+
className: `child-cell${isStacking ? " stack-td" : ""}`, children: [child, isStacking &&
|
|
2944
|
+
index < numChildren - 1 &&
|
|
2945
|
+
config.gap && (jsx("div", { className: "mobile-gap-spacer", style: {
|
|
2946
|
+
display: "none",
|
|
2947
|
+
fontSize: "0",
|
|
2948
|
+
lineHeight: "0",
|
|
2949
|
+
height: config.gap,
|
|
2950
|
+
background: "transparent",
|
|
2951
|
+
}, children: "\u00A0" }))] }), index < numChildren - 1 &&
|
|
2952
|
+
config.gap && (jsx("td", { width: config.gap, style: gapTdStyle,
|
|
2953
|
+
// Mirror of Container's desktop-gap-column pattern:
|
|
2954
|
+
// when isStacking, the non-@media .desktop-gap-column
|
|
2955
|
+
// rule collapses the between-column gap td so it does
|
|
2956
|
+
// not create phantom space while children are stacked.
|
|
2957
|
+
className: `row-gap-td${isStacking ? " desktop-gap-column" : ""}`, children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`));
|
|
2958
|
+
}) }) }) }) }) }) }) }) }) }) }) }) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2821
2959
|
if (href && !devMode) {
|
|
2822
|
-
return (jsx("a", { href: href, ...({ target }), style: {
|
|
2960
|
+
return (jsx("a", { href: href, ...({ target }), ...rootBindingProps(bindings), style: {
|
|
2823
2961
|
textDecoration: "none",
|
|
2824
2962
|
color: "inherit",
|
|
2825
2963
|
display: "block",
|
|
@@ -2864,10 +3002,10 @@ function getBorderStyle$1(border) {
|
|
|
2864
3002
|
}
|
|
2865
3003
|
return style;
|
|
2866
3004
|
}
|
|
2867
|
-
const Section = ({ config, children, devNode, }) => {
|
|
3005
|
+
const Section = ({ config, children, devNode, bindings, }) => {
|
|
2868
3006
|
var _a, _b, _c;
|
|
2869
3007
|
const { sectionType, padding } = config;
|
|
2870
|
-
return (jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
3008
|
+
return (jsxs("table", { "aria-label": `Section |Table | ${sectionType}`, role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2871
3009
|
position: "relative",
|
|
2872
3010
|
width: "100%",
|
|
2873
3011
|
backgroundColor: config.backgroundColor,
|
|
@@ -2880,58 +3018,84 @@ const Section = ({ config, children, devNode, }) => {
|
|
|
2880
3018
|
backgroundPosition: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.position,
|
|
2881
3019
|
}, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: {
|
|
2882
3020
|
padding: padding,
|
|
2883
|
-
}, children: children }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children:
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
3021
|
+
}, ...listBindingProps(bindings), children: children }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: jsxs("span", { style: {
|
|
3022
|
+
backgroundColor: "black",
|
|
3023
|
+
color: "white",
|
|
3024
|
+
padding: "4px",
|
|
3025
|
+
fontSize: "14px",
|
|
3026
|
+
position: "absolute",
|
|
3027
|
+
left: 0,
|
|
3028
|
+
top: 0,
|
|
3029
|
+
}, children: ["Section | ", sectionType] }) }) }) }))] }));
|
|
2892
3030
|
};
|
|
2893
3031
|
var Section_default = memo(Section, arePropsEqual);
|
|
2894
3032
|
|
|
2895
|
-
function Spacer({ config, devNode }) {
|
|
2896
|
-
|
|
3033
|
+
function Spacer({ config, devNode, bindings }) {
|
|
3034
|
+
var _a, _b, _c;
|
|
3035
|
+
const { height, hideOnMobile, backgroundColor, backgroundImage } = config;
|
|
2897
3036
|
// 1. Spacer Table Style
|
|
2898
3037
|
const spacerTableStyle = {
|
|
2899
|
-
// Crucial for compatibility: Ensures no background or border interference
|
|
2900
|
-
backgroundColor: "transparent",
|
|
2901
3038
|
borderCollapse: "collapse",
|
|
2902
|
-
border: "0",
|
|
2903
3039
|
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
3040
|
};
|
|
2910
3041
|
// 2. Spacer TD Style: The element that creates the actual vertical space
|
|
2911
3042
|
const spacerTdStyle = {
|
|
2912
3043
|
height: height,
|
|
2913
|
-
|
|
3044
|
+
maxHeight: height,
|
|
2914
3045
|
fontSize: "0",
|
|
2915
3046
|
lineHeight: "0",
|
|
2916
3047
|
padding: "0",
|
|
3048
|
+
margin: "0",
|
|
3049
|
+
border: "none",
|
|
3050
|
+
color: "transparent",
|
|
3051
|
+
// Background applied at TD level for Outlook Classic compatibility
|
|
3052
|
+
...(backgroundColor && { backgroundColor }),
|
|
3053
|
+
...(backgroundImage && {
|
|
3054
|
+
backgroundImage: `url(${backgroundImage.src})`,
|
|
3055
|
+
backgroundRepeat: (_a = backgroundImage.repeat) !== null && _a !== void 0 ? _a : "no-repeat",
|
|
3056
|
+
backgroundSize: (_b = backgroundImage.size) !== null && _b !== void 0 ? _b : "cover",
|
|
3057
|
+
backgroundPosition: (_c = backgroundImage.position) !== null && _c !== void 0 ? _c : "center",
|
|
3058
|
+
}),
|
|
2917
3059
|
};
|
|
2918
3060
|
// Parse height for the HTML attribute
|
|
2919
3061
|
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: {
|
|
3062
|
+
return (jsxs("table", { "aria-label": "Vertical Spacer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2923
3063
|
// --- Start dev
|
|
2924
3064
|
position: "relative",
|
|
2925
3065
|
// --- End dev
|
|
2926
3066
|
...spacerTableStyle,
|
|
2927
|
-
}, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: spacerTdStyle,
|
|
2928
|
-
|
|
2929
|
-
|
|
3067
|
+
}, ...{ height: spacerHeightAttribute }, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: spacerTdStyle, height: spacerHeightAttribute, ...(backgroundColor && !backgroundImage
|
|
3068
|
+
? { bgcolor: backgroundColor }
|
|
3069
|
+
: {}) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2930
3070
|
}
|
|
2931
3071
|
var Spacer_default = memo(Spacer, arePropsEqual);
|
|
2932
3072
|
|
|
2933
|
-
|
|
2934
|
-
|
|
3073
|
+
// Helper to build link href based on innerLink type
|
|
3074
|
+
function buildLinkHref$1(innerLink) {
|
|
3075
|
+
if (!innerLink || innerLink.type === "none")
|
|
3076
|
+
return null;
|
|
3077
|
+
switch (innerLink.type) {
|
|
3078
|
+
case "url":
|
|
3079
|
+
return innerLink.url || null;
|
|
3080
|
+
case "email":
|
|
3081
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
3082
|
+
case "phone":
|
|
3083
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
3084
|
+
case "anchor":
|
|
3085
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
3086
|
+
case "page_top":
|
|
3087
|
+
return "#top";
|
|
3088
|
+
case "page_bottom":
|
|
3089
|
+
return "#bottom";
|
|
3090
|
+
default:
|
|
3091
|
+
return null;
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
function Text({ config, devMode, children, bindings }) {
|
|
3095
|
+
const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth, innerLink, } = config;
|
|
3096
|
+
// Resolve href and target from innerLink
|
|
3097
|
+
const href = buildLinkHref$1(innerLink);
|
|
3098
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2935
3099
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
2936
3100
|
// When maxWidth is set, this TD stays at width: 100% so it always fills
|
|
2937
3101
|
// its parent — the inner maxWidth table (see below) does the actual
|
|
@@ -2984,26 +3148,31 @@ function Text({ config, devMode, children }) {
|
|
|
2984
3148
|
? injectLinkStyles(content, contentStyle)
|
|
2985
3149
|
: "";
|
|
2986
3150
|
const innerContent = isString ? (jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsx("div", { style: contentStyle, children: content }));
|
|
2987
|
-
|
|
3151
|
+
const wrappedContent = maxWidth ? (
|
|
3152
|
+
/*
|
|
3153
|
+
* maxWidth wrapper — Outlook Classic compatibility pattern:
|
|
3154
|
+
*
|
|
3155
|
+
* <center> instructs the Word rendering engine to horizontally
|
|
3156
|
+
* centre its child block, equivalent to margin: 0 auto in CSS.
|
|
3157
|
+
*
|
|
3158
|
+
* The inner table carries the `width` HTML attribute set to the
|
|
3159
|
+
* maxWidth value. Outlook Classic reads `width` as a hard pixel
|
|
3160
|
+
* cap; it has no concept of max-width so this is the only lever
|
|
3161
|
+
* available. Modern clients receive the CSS max-width on the
|
|
3162
|
+
* same table and behave correctly.
|
|
3163
|
+
*
|
|
3164
|
+
* The outer TD remains at width: 100% so it always fills its
|
|
3165
|
+
* parent cell in every client — only the inner content is capped.
|
|
3166
|
+
*/
|
|
3167
|
+
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);
|
|
3168
|
+
return (jsx("table", { "aria-label": "Text Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, ...rootBindingProps(bindings), style: {
|
|
2988
3169
|
width: "100%",
|
|
2989
3170
|
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) }) }) }) }));
|
|
3171
|
+
}, 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: {
|
|
3172
|
+
display: "block",
|
|
3173
|
+
textDecoration: "none",
|
|
3174
|
+
color: "inherit",
|
|
3175
|
+
}, children: wrappedContent })) : (wrappedContent) }) }) }) }));
|
|
3007
3176
|
}
|
|
3008
3177
|
var Text_default = memo(Text, arePropsEqual);
|
|
3009
3178
|
|
|
@@ -3129,7 +3298,7 @@ function buildLinkHref(innerLink) {
|
|
|
3129
3298
|
return null;
|
|
3130
3299
|
}
|
|
3131
3300
|
}
|
|
3132
|
-
function Icon({ config, devNode, devMode, children }) {
|
|
3301
|
+
function Icon({ config, devNode, devMode, children, bindings }) {
|
|
3133
3302
|
const {
|
|
3134
3303
|
// base64Source,
|
|
3135
3304
|
width, height, backgroundColor, padding = "0", borderRadius = "0", border, innerLink, justifyContent = "center", } = config;
|
|
@@ -3264,7 +3433,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
3264
3433
|
<!--<![endif]-->
|
|
3265
3434
|
`
|
|
3266
3435
|
: null;
|
|
3267
|
-
return (jsxs("table", { "aria-label": "Icon", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, style: {
|
|
3436
|
+
return (jsxs("table", { "aria-label": "Icon", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, ...rootBindingProps(bindings), style: {
|
|
3268
3437
|
// --- Start dev
|
|
3269
3438
|
position: "relative",
|
|
3270
3439
|
// --- End dev
|