@pagenflow/email 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Row.d.ts +5 -0
- package/dist/index.cjs.js +306 -23
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +307 -25
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/components/Row.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ export interface RowConfig {
|
|
|
17
17
|
backgroundImage?: BackgroundImageType;
|
|
18
18
|
borderRadius?: string;
|
|
19
19
|
border?: BorderConfig;
|
|
20
|
+
mobile?: {
|
|
21
|
+
justifyContent?: JustifyContent;
|
|
22
|
+
alignItems?: AlignItems;
|
|
23
|
+
wrap?: boolean;
|
|
24
|
+
};
|
|
20
25
|
}
|
|
21
26
|
export type RowProps = {
|
|
22
27
|
children: ReactNode;
|
package/dist/index.cjs.js
CHANGED
|
@@ -1526,7 +1526,7 @@ function arePropsEqual(prevProps, nextProps) {
|
|
|
1526
1526
|
}
|
|
1527
1527
|
|
|
1528
1528
|
// Map alignment to HTML 'align' attribute
|
|
1529
|
-
const justifyMap$
|
|
1529
|
+
const justifyMap$3 = {
|
|
1530
1530
|
start: "left",
|
|
1531
1531
|
center: "center",
|
|
1532
1532
|
end: "right",
|
|
@@ -1549,7 +1549,7 @@ function Button({ config, devMode }) {
|
|
|
1549
1549
|
const vmlFillColor = backgroundColor.startsWith("#")
|
|
1550
1550
|
? backgroundColor
|
|
1551
1551
|
: `#${backgroundColor}`;
|
|
1552
|
-
const align = justifyMap$
|
|
1552
|
+
const align = justifyMap$3[justifyContent];
|
|
1553
1553
|
// Build VML font styles
|
|
1554
1554
|
const vmlFontWeight = fontWeight || "bold";
|
|
1555
1555
|
const vmlFontStyle = fontStyle === "italic" ? "font-style:italic;" : "";
|
|
@@ -1712,7 +1712,7 @@ const alignMap$1 = {
|
|
|
1712
1712
|
center: "middle",
|
|
1713
1713
|
end: "bottom",
|
|
1714
1714
|
};
|
|
1715
|
-
const justifyMap$
|
|
1715
|
+
const justifyMap$2 = {
|
|
1716
1716
|
start: "left",
|
|
1717
1717
|
center: "center",
|
|
1718
1718
|
end: "right",
|
|
@@ -1816,7 +1816,7 @@ function Container({ children, config, devMode, devNode }) {
|
|
|
1816
1816
|
fontSize: "1px",
|
|
1817
1817
|
};
|
|
1818
1818
|
const justifyAlign = config.justifyContent
|
|
1819
|
-
? justifyMap$
|
|
1819
|
+
? justifyMap$2[config.justifyContent]
|
|
1820
1820
|
: "center";
|
|
1821
1821
|
const containerWidthAttr = widthType === "fixed" ? containerWidthPx : undefined;
|
|
1822
1822
|
const isStacking = config.shouldWrap && numChildren > 1;
|
|
@@ -1926,14 +1926,14 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
1926
1926
|
}
|
|
1927
1927
|
`;
|
|
1928
1928
|
const globalStyles = `
|
|
1929
|
-
@media screen and (max-width:
|
|
1929
|
+
@media screen and (max-width: 768px) {
|
|
1930
1930
|
.container-fixed-width {
|
|
1931
1931
|
width: 100% !important;
|
|
1932
1932
|
max-width: 100% !important;
|
|
1933
1933
|
}
|
|
1934
1934
|
}
|
|
1935
1935
|
|
|
1936
|
-
@media screen and (max-width:
|
|
1936
|
+
@media screen and (max-width: 768px) {
|
|
1937
1937
|
.stack-td {
|
|
1938
1938
|
width: 100% !important;
|
|
1939
1939
|
display: block !important;
|
|
@@ -1956,6 +1956,122 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
1956
1956
|
mso-line-height-rule: exactly;
|
|
1957
1957
|
}
|
|
1958
1958
|
}
|
|
1959
|
+
|
|
1960
|
+
@media only screen and (max-width: 768px) {
|
|
1961
|
+
/* 1. Handling Mobile Alignment (Justify) - Works for both wrapped and non-wrapped */
|
|
1962
|
+
/* We target the inner table alignment */
|
|
1963
|
+
.responsive-row[data-mobile-justify="center"] .content-table {
|
|
1964
|
+
margin: 0 auto !important;
|
|
1965
|
+
float: none !important;
|
|
1966
|
+
}
|
|
1967
|
+
.responsive-row[data-mobile-justify="start"] .content-table {
|
|
1968
|
+
margin: 0 !important;
|
|
1969
|
+
float: left !important;
|
|
1970
|
+
}
|
|
1971
|
+
.responsive-row[data-mobile-justify="end"] .content-table {
|
|
1972
|
+
margin: 0 0 0 auto !important;
|
|
1973
|
+
float: right !important;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
/* Mobile justify for wrapped children - we need to target the outer wrapper td */
|
|
1977
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-justify="center"] td[align] {
|
|
1978
|
+
text-align: center !important;
|
|
1979
|
+
}
|
|
1980
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-justify="start"] td[align] {
|
|
1981
|
+
text-align: left !important;
|
|
1982
|
+
}
|
|
1983
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-justify="end"] td[align] {
|
|
1984
|
+
text-align: right !important;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
/* Also apply to child content tables for better support */
|
|
1988
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-justify="center"] .child-cell table {
|
|
1989
|
+
margin-left: auto !important;
|
|
1990
|
+
margin-right: auto !important;
|
|
1991
|
+
}
|
|
1992
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-justify="start"] .child-cell table {
|
|
1993
|
+
margin-left: 0 !important;
|
|
1994
|
+
margin-right: auto !important;
|
|
1995
|
+
}
|
|
1996
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-justify="end"] .child-cell table {
|
|
1997
|
+
margin-left: auto !important;
|
|
1998
|
+
margin-right: 0 !important;
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
/* 2. Handling Mobile Vertical Alignment (Align Items) */
|
|
2002
|
+
/* For non-wrapped rows - controls vertical alignment when cells are side-by-side */
|
|
2003
|
+
.responsive-row[data-mobile-align="center"]:not([data-mobile-wrap="true"]) .child-cell {
|
|
2004
|
+
vertical-align: middle !important;
|
|
2005
|
+
}
|
|
2006
|
+
.responsive-row[data-mobile-align="start"]:not([data-mobile-wrap="true"]) .child-cell {
|
|
2007
|
+
vertical-align: top !important;
|
|
2008
|
+
}
|
|
2009
|
+
.responsive-row[data-mobile-align="end"]:not([data-mobile-wrap="true"]) .child-cell {
|
|
2010
|
+
vertical-align: bottom !important;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
/* For wrapped rows - alignItems controls vertical alignment of content within each child cell */
|
|
2014
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-align="center"] .child-cell {
|
|
2015
|
+
vertical-align: middle !important;
|
|
2016
|
+
}
|
|
2017
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-align="start"] .child-cell {
|
|
2018
|
+
vertical-align: top !important;
|
|
2019
|
+
}
|
|
2020
|
+
.responsive-row[data-mobile-wrap="true"][data-mobile-align="end"] .child-cell {
|
|
2021
|
+
vertical-align: bottom !important;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
/* 3. Handling Mobile Wrap - Pure CSS Solution */
|
|
2025
|
+
/* Force table to act like block container */
|
|
2026
|
+
.responsive-row[data-mobile-wrap="true"] .content-table {
|
|
2027
|
+
width: 100% !important;
|
|
2028
|
+
max-width: 100% !important;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
/* Force table row to stack cells */
|
|
2032
|
+
.responsive-row[data-mobile-wrap="true"] .content-tr {
|
|
2033
|
+
display: block !important;
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
/* Force each child cell to be full width block */
|
|
2037
|
+
.responsive-row[data-mobile-wrap="true"] .child-cell {
|
|
2038
|
+
display: block !important;
|
|
2039
|
+
width: 100% !important;
|
|
2040
|
+
box-sizing: border-box !important;
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
/* Hide horizontal gap cells and create vertical spacing with padding */
|
|
2044
|
+
.responsive-row[data-mobile-wrap="true"] .row-gap-td {
|
|
2045
|
+
display: none !important;
|
|
2046
|
+
width: 0 !important;
|
|
2047
|
+
height: 0 !important;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
/* Add vertical spacing between stacked cells using margin */
|
|
2051
|
+
.responsive-row[data-mobile-wrap="true"] .child-cell:not(:last-child) {
|
|
2052
|
+
margin-bottom: 20px !important;
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
/* Dynamic gap support - common values */
|
|
2056
|
+
.responsive-row[data-mobile-wrap="true"][data-gap="10px"] .child-cell:not(:last-child) {
|
|
2057
|
+
margin-bottom: 10px !important;
|
|
2058
|
+
}
|
|
2059
|
+
.responsive-row[data-mobile-wrap="true"][data-gap="15px"] .child-cell:not(:last-child) {
|
|
2060
|
+
margin-bottom: 15px !important;
|
|
2061
|
+
}
|
|
2062
|
+
.responsive-row[data-mobile-wrap="true"][data-gap="20px"] .child-cell:not(:last-child) {
|
|
2063
|
+
margin-bottom: 20px !important;
|
|
2064
|
+
}
|
|
2065
|
+
.responsive-row[data-mobile-wrap="true"][data-gap="24px"] .child-cell:not(:last-child) {
|
|
2066
|
+
margin-bottom: 24px !important;
|
|
2067
|
+
}
|
|
2068
|
+
.responsive-row[data-mobile-wrap="true"][data-gap="30px"] .child-cell:not(:last-child) {
|
|
2069
|
+
margin-bottom: 30px !important;
|
|
2070
|
+
}
|
|
2071
|
+
.responsive-row[data-mobile-wrap="true"][data-gap="40px"] .child-cell:not(:last-child) {
|
|
2072
|
+
margin-bottom: 40px !important;
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
1959
2075
|
|
|
1960
2076
|
/* ================================================= */
|
|
1961
2077
|
/* 🔒 UNIVERSAL LINK RESET */
|
|
@@ -2152,7 +2268,7 @@ function Image({ config, devNode, devMode }) {
|
|
|
2152
2268
|
}
|
|
2153
2269
|
var Image_default = React.memo(Image, arePropsEqual);
|
|
2154
2270
|
|
|
2155
|
-
const justifyMap = {
|
|
2271
|
+
const justifyMap$1 = {
|
|
2156
2272
|
start: "left",
|
|
2157
2273
|
center: "center",
|
|
2158
2274
|
end: "right",
|
|
@@ -2184,7 +2300,7 @@ function getBorderStyle$1(border) {
|
|
|
2184
2300
|
return style;
|
|
2185
2301
|
}
|
|
2186
2302
|
function Row({ children, config, devNode }) {
|
|
2187
|
-
var _a, _b, _c;
|
|
2303
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2188
2304
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2189
2305
|
const numChildren = childrenArray.length;
|
|
2190
2306
|
// 1. Outer TD for Background and Border Radius (no border here)
|
|
@@ -2217,7 +2333,7 @@ function Row({ children, config, devNode }) {
|
|
|
2217
2333
|
fontSize: "1px",
|
|
2218
2334
|
};
|
|
2219
2335
|
const tdAlign = config.justifyContent
|
|
2220
|
-
? justifyMap[config.justifyContent]
|
|
2336
|
+
? justifyMap$1[config.justifyContent]
|
|
2221
2337
|
: "left";
|
|
2222
2338
|
const tdValign = config.alignItems ? alignMap[config.alignItems] : "top";
|
|
2223
2339
|
return (jsxRuntime.jsxs("table", Object.assign({ "aria-label": "Row Outer", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
@@ -2225,17 +2341,17 @@ function Row({ children, config, devNode }) {
|
|
|
2225
2341
|
width: config.width || "100%",
|
|
2226
2342
|
height: config.height,
|
|
2227
2343
|
borderCollapse: "collapse",
|
|
2228
|
-
} }, (config.height && { height: config.height }), { children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", Object.assign({ style: backgroundTdStyle }, (config.height && { height: config.height }), { children: jsxRuntime.jsx("table", { "aria-label": "Row Border Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: borderTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: paddingTdStyle, children: jsxRuntime.jsx("table", { "aria-label": "Row Justification Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2344
|
+
} }, (config.height && { height: config.height }), { "data-mobile-justify": (_d = config.mobile) === null || _d === void 0 ? void 0 : _d.justifyContent, "data-mobile-align": (_e = config.mobile) === null || _e === void 0 ? void 0 : _e.alignItems, "data-mobile-wrap": ((_f = config.mobile) === null || _f === void 0 ? void 0 : _f.wrap) ? "true" : undefined, "data-gap": config.gap, className: "responsive-row", children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", Object.assign({ style: backgroundTdStyle }, (config.height && { height: config.height }), { children: jsxRuntime.jsx("table", { "aria-label": "Row Border Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: borderTableStyle, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: paddingTdStyle, children: jsxRuntime.jsx("table", { "aria-label": "Row Justification Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2229
2345
|
width: "100%",
|
|
2230
2346
|
height: "100%",
|
|
2231
2347
|
borderCollapse: "collapse",
|
|
2232
|
-
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: tdAlign, children: jsxRuntime.jsx("table", Object.assign({ "aria-label": "Row Content", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: contentTableStyle }, (config.height && { height: config.height }), { children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("td", { valign: tdValign, style: {
|
|
2348
|
+
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: tdAlign, children: jsxRuntime.jsx("table", Object.assign({ "aria-label": "Row Content", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: contentTableStyle }, (config.height && { height: config.height }), { className: "content-table", children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { className: "content-tr", children: childrenArray.map((child, index) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("td", { valign: tdValign, style: {
|
|
2233
2349
|
verticalAlign: tdValign,
|
|
2234
2350
|
textAlign: "left",
|
|
2235
2351
|
padding: "0",
|
|
2236
2352
|
margin: "0",
|
|
2237
|
-
}, children: child }), index < numChildren - 1 &&
|
|
2238
|
-
config.gap && (jsxRuntime.jsx("td", { width: config.gap, style: gapTdStyle, children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) })) }) }) }) }) }) }) }) }) })) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
|
|
2353
|
+
}, className: "child-cell", children: child }), index < numChildren - 1 &&
|
|
2354
|
+
config.gap && (jsxRuntime.jsx("td", { width: config.gap, style: gapTdStyle, className: "row-gap-td", children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) })) }) }) }) }) }) }) }) }) })) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })));
|
|
2239
2355
|
}
|
|
2240
2356
|
var Row_default = React.memo(Row, arePropsEqual);
|
|
2241
2357
|
|
|
@@ -2316,7 +2432,6 @@ function Spacer({ config, devNode }) {
|
|
|
2316
2432
|
var Spacer_default = React.memo(Spacer, arePropsEqual);
|
|
2317
2433
|
|
|
2318
2434
|
function Text({ config, devMode, children }) {
|
|
2319
|
-
var _a;
|
|
2320
2435
|
const { text, padding, color, textAlign, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, } = config;
|
|
2321
2436
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
2322
2437
|
const tdStyle = {
|
|
@@ -2325,9 +2440,7 @@ function Text({ config, devMode, children }) {
|
|
|
2325
2440
|
width: "100%",
|
|
2326
2441
|
verticalAlign: "top",
|
|
2327
2442
|
};
|
|
2328
|
-
// 2. Content Style: Applied directly to a wrapper element
|
|
2329
|
-
// or inherited by the children. For max compatibility, we apply core styles
|
|
2330
|
-
// directly to the TD or a wrapper <p> (if children is just a string).
|
|
2443
|
+
// 2. Content Style: Applied directly to a wrapper element
|
|
2331
2444
|
const contentStyle = {
|
|
2332
2445
|
color: color,
|
|
2333
2446
|
textAlign: textAlign,
|
|
@@ -2342,19 +2455,188 @@ function Text({ config, devMode, children }) {
|
|
|
2342
2455
|
verticalAlign: verticalAlign,
|
|
2343
2456
|
opacity: opacity,
|
|
2344
2457
|
whiteSpace: whiteSpace,
|
|
2345
|
-
margin: "0",
|
|
2458
|
+
margin: "0",
|
|
2346
2459
|
padding: "0",
|
|
2347
|
-
fontFamily: "Arial, Helvetica, sans-serif",
|
|
2460
|
+
fontFamily: "Arial, Helvetica, sans-serif",
|
|
2348
2461
|
};
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2462
|
+
// Determine content to render
|
|
2463
|
+
const content = text !== null && text !== void 0 ? text : children;
|
|
2464
|
+
const isString = typeof content === "string";
|
|
2465
|
+
return (jsxRuntime.jsx("table", { "aria-label": "Text Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2352
2466
|
width: "100%",
|
|
2353
2467
|
borderCollapse: "collapse",
|
|
2354
|
-
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: tdStyle, align: textAlign, children: jsxRuntime.jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html:
|
|
2468
|
+
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { style: tdStyle, align: textAlign, children: isString ? (jsxRuntime.jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html: content } })) : (jsxRuntime.jsx("div", { style: contentStyle, children: content })) }) }) }) }));
|
|
2355
2469
|
}
|
|
2356
2470
|
var Text_default = React.memo(Text, arePropsEqual);
|
|
2357
2471
|
|
|
2472
|
+
// Map alignment to HTML 'align' attribute
|
|
2473
|
+
const justifyMap = {
|
|
2474
|
+
start: "left",
|
|
2475
|
+
center: "center",
|
|
2476
|
+
end: "right",
|
|
2477
|
+
};
|
|
2478
|
+
// Helper to build Iconify API URL
|
|
2479
|
+
function buildIconifyUrl(config) {
|
|
2480
|
+
const { iconIdentifier, height = 24, color = "000000", rotate = 0, rotateOrientation = "cw", } = config;
|
|
2481
|
+
if (!iconIdentifier)
|
|
2482
|
+
return null;
|
|
2483
|
+
// Remove # from color if present
|
|
2484
|
+
const cleanColor = color.replace("#", "");
|
|
2485
|
+
// Build URL from template
|
|
2486
|
+
const template = process.env.ICONIFY_API_IMAGE_URI ||
|
|
2487
|
+
"https://iconify.pagenflow.com/api/image/{{height}}/{{color}}/{{rotate}}-{{rotate-orientation}}/{{icon-full-name}}.png";
|
|
2488
|
+
return template
|
|
2489
|
+
.replace("{{height}}", String(Number(height) * Number(2)))
|
|
2490
|
+
.replace("{{color}}", cleanColor)
|
|
2491
|
+
.replace("{{rotate}}", String(rotate))
|
|
2492
|
+
.replace("{{rotate-orientation}}", rotateOrientation)
|
|
2493
|
+
.replace("{{icon-full-name}}", iconIdentifier);
|
|
2494
|
+
}
|
|
2495
|
+
// Helper to build link href based on innerLink type
|
|
2496
|
+
function buildLinkHref(innerLink) {
|
|
2497
|
+
if (!innerLink || innerLink.type === "none")
|
|
2498
|
+
return null;
|
|
2499
|
+
switch (innerLink.type) {
|
|
2500
|
+
case "url":
|
|
2501
|
+
return innerLink.url || null;
|
|
2502
|
+
case "email":
|
|
2503
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
2504
|
+
case "phone":
|
|
2505
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
2506
|
+
case "anchor":
|
|
2507
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
2508
|
+
case "page_top":
|
|
2509
|
+
return "#top";
|
|
2510
|
+
case "page_bottom":
|
|
2511
|
+
return "#bottom";
|
|
2512
|
+
default:
|
|
2513
|
+
return null;
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
function Icon({ config, devNode, devMode, children }) {
|
|
2517
|
+
const {
|
|
2518
|
+
// base64Source,
|
|
2519
|
+
width, height, backgroundColor, padding = "0", borderRadius = "0", innerLink, justifyContent = "center", } = config;
|
|
2520
|
+
// Determine icon source
|
|
2521
|
+
const iconSrc = buildIconifyUrl(config);
|
|
2522
|
+
const href = buildLinkHref(innerLink);
|
|
2523
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_self";
|
|
2524
|
+
const align = justifyMap[justifyContent];
|
|
2525
|
+
// Convert width/height to string with px if number
|
|
2526
|
+
const widthStr = typeof width === "number" ? `${width}px` : width;
|
|
2527
|
+
const heightStr = typeof height === "number" ? `${height}px` : height;
|
|
2528
|
+
// Parse numeric values for HTML attributes
|
|
2529
|
+
const widthNum = typeof width === "number"
|
|
2530
|
+
? width
|
|
2531
|
+
: typeof width === "string" && width.endsWith("px")
|
|
2532
|
+
? parseInt(width, 10)
|
|
2533
|
+
: undefined;
|
|
2534
|
+
const heightNum = typeof height === "number"
|
|
2535
|
+
? height
|
|
2536
|
+
: typeof height === "string" && height.endsWith("px")
|
|
2537
|
+
? parseInt(height, 10)
|
|
2538
|
+
: undefined;
|
|
2539
|
+
// 1. Image Style: Critical for compatibility
|
|
2540
|
+
const imgStyle = {
|
|
2541
|
+
display: "block", // Prevents extra vertical space
|
|
2542
|
+
border: 0, // No default border
|
|
2543
|
+
width: widthStr || "auto",
|
|
2544
|
+
height: heightStr || "auto",
|
|
2545
|
+
};
|
|
2546
|
+
// 2. Link Style: No underline or color changes
|
|
2547
|
+
const linkStyle = {
|
|
2548
|
+
display: "block",
|
|
2549
|
+
textDecoration: "none",
|
|
2550
|
+
border: 0,
|
|
2551
|
+
outline: "none",
|
|
2552
|
+
};
|
|
2553
|
+
// 3. TD Style: Padding and background
|
|
2554
|
+
const tdStyle = {
|
|
2555
|
+
padding: padding,
|
|
2556
|
+
backgroundColor: backgroundColor,
|
|
2557
|
+
fontSize: "0", // CRITICAL: Collapses extra space
|
|
2558
|
+
lineHeight: "0", // CRITICAL: Collapses extra space7
|
|
2559
|
+
borderRadius: borderRadius,
|
|
2560
|
+
overflow: "hidden",
|
|
2561
|
+
};
|
|
2562
|
+
// --- VML Calculation for Outlook Compatibility ---
|
|
2563
|
+
const numericPadding = parseInt(padding.split(" ")[0] || "0", 10);
|
|
2564
|
+
const vmlWidth = (widthNum || 24) + numericPadding * 2;
|
|
2565
|
+
const vmlHeight = (heightNum || 24) + numericPadding * 2;
|
|
2566
|
+
// VML colors must use full hex format
|
|
2567
|
+
const vmlFillColor = (backgroundColor === null || backgroundColor === void 0 ? void 0 : backgroundColor.startsWith("#"))
|
|
2568
|
+
? backgroundColor
|
|
2569
|
+
: backgroundColor
|
|
2570
|
+
? `#${backgroundColor}`
|
|
2571
|
+
: "#ffffff";
|
|
2572
|
+
// Calculate arcsize percentage for VML
|
|
2573
|
+
const numericBorderRadius = parseInt(borderRadius || "0", 10);
|
|
2574
|
+
const arcsize = numericBorderRadius > 0
|
|
2575
|
+
? Math.min((numericBorderRadius / Math.min(vmlWidth, vmlHeight)) * 100, 100)
|
|
2576
|
+
: 0;
|
|
2577
|
+
// Build VML code for Outlook
|
|
2578
|
+
const vmlIcon = backgroundColor && numericBorderRadius > 0
|
|
2579
|
+
? `
|
|
2580
|
+
<!--[if mso]>
|
|
2581
|
+
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" ${href && !devMode ? `href="${href}"` : ""} style="height:${vmlHeight}px;width:${vmlWidth}px;v-text-anchor:middle;" arcsize="${arcsize}%" stroke="false" fillcolor="${vmlFillColor}">
|
|
2582
|
+
<w:anchorlock/>
|
|
2583
|
+
<v:textbox inset="0,0,0,0" style="text-align: center;">
|
|
2584
|
+
<center style="padding:${padding};">
|
|
2585
|
+
<img src="${iconSrc || ""}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;" />
|
|
2586
|
+
</center>
|
|
2587
|
+
</v:textbox>
|
|
2588
|
+
</v:roundrect>
|
|
2589
|
+
<![endif]-->
|
|
2590
|
+
`
|
|
2591
|
+
: "";
|
|
2592
|
+
// If no icon source, return empty
|
|
2593
|
+
if (!iconSrc && !devMode) {
|
|
2594
|
+
return null;
|
|
2595
|
+
}
|
|
2596
|
+
// Icon image element
|
|
2597
|
+
const iconElement = devMode && !!children ? (children) : iconSrc ? (jsxRuntime.jsx("img", { draggable: false, src: iconSrc, alt: "" // Icons are decorative, empty alt is appropriate
|
|
2598
|
+
, style: imgStyle, width: widthNum, height: heightNum, border: 0 })) : (jsxRuntime.jsx(jsxRuntime.Fragment, {}));
|
|
2599
|
+
// Wrap in link if href exists and not in dev mode
|
|
2600
|
+
const content = href && !devMode ? (jsxRuntime.jsx("a", Object.assign({ href: href, target: target, style: linkStyle }, (target === "_blank" ? { rel: "noopener noreferrer" } : {}), { children: iconElement }))) : (iconElement);
|
|
2601
|
+
// Build the HTML content with VML support (only when NOT in dev mode)
|
|
2602
|
+
const useVML = !devMode && backgroundColor && numericBorderRadius > 0;
|
|
2603
|
+
const htmlContent = useVML
|
|
2604
|
+
? `
|
|
2605
|
+
${vmlIcon}
|
|
2606
|
+
<!--[if !mso]><!-->
|
|
2607
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
|
|
2608
|
+
<tbody>
|
|
2609
|
+
<tr>
|
|
2610
|
+
<td style="background-color: ${backgroundColor}; border-radius: ${borderRadius}; padding: ${padding}; font-size: 0; line-height: 0; overflow: hidden;">
|
|
2611
|
+
${href
|
|
2612
|
+
? `<a href="${href}" target="${target}" style="display:block;text-decoration:none;border:0;outline:none;" ${target === "_blank" ? 'rel="noopener noreferrer"' : ""}>
|
|
2613
|
+
<img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};" />
|
|
2614
|
+
</a>`
|
|
2615
|
+
: `<img draggable="false" src="${iconSrc}" alt="" width="${widthNum || 24}" height="${heightNum || 24}" border="0" style="display:block;border:0;width:${widthStr || "auto"};height:${heightStr || "auto"};" />`}
|
|
2616
|
+
</td>
|
|
2617
|
+
</tr>
|
|
2618
|
+
</tbody>
|
|
2619
|
+
</table>
|
|
2620
|
+
<!--<![endif]-->
|
|
2621
|
+
`
|
|
2622
|
+
: null;
|
|
2623
|
+
return (jsxRuntime.jsxs("table", { "aria-label": "Icon", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: align, style: {
|
|
2624
|
+
// --- Start dev
|
|
2625
|
+
position: "relative",
|
|
2626
|
+
// --- End dev
|
|
2627
|
+
width: widthStr || "auto",
|
|
2628
|
+
borderCollapse: "collapse",
|
|
2629
|
+
// base
|
|
2630
|
+
boxSizing: "border-box",
|
|
2631
|
+
border: 0,
|
|
2632
|
+
margin: 0,
|
|
2633
|
+
padding: 0,
|
|
2634
|
+
}, onClick: devMode ? (e) => e.preventDefault() : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: useVML ? (jsxRuntime.jsx("td", { dangerouslySetInnerHTML: {
|
|
2635
|
+
__html: htmlContent !== null && htmlContent !== void 0 ? htmlContent : "",
|
|
2636
|
+
} })) : (jsxRuntime.jsx("td", { style: tdStyle, align: align, children: content })) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
|
|
2637
|
+
}
|
|
2638
|
+
var Icon_default = React.memo(Icon, arePropsEqual);
|
|
2639
|
+
|
|
2358
2640
|
exports.Body = Body;
|
|
2359
2641
|
exports.Button = Button_default;
|
|
2360
2642
|
exports.Column = Column_default;
|
|
@@ -2363,6 +2645,7 @@ exports.Divider = Divider_default;
|
|
|
2363
2645
|
exports.Head = Head;
|
|
2364
2646
|
exports.Heading = Heading_default;
|
|
2365
2647
|
exports.Html = Html;
|
|
2648
|
+
exports.Icon = Icon_default;
|
|
2366
2649
|
exports.Image = Image_default;
|
|
2367
2650
|
exports.Row = Row_default;
|
|
2368
2651
|
exports.Section = Section_default;
|