@pagenflow/email 1.4.6 → 1.4.7
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/Column.d.ts +1 -0
- package/dist/components/Text.d.ts +7 -0
- package/dist/index.cjs.js +104 -43
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +104 -43
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1801,6 +1801,9 @@ function Column({ children, config, devNode }) {
|
|
|
1801
1801
|
};
|
|
1802
1802
|
// 2. Outer TD style: Background and Border Radius (no border here).
|
|
1803
1803
|
// height is set so the TD occupies the full declared height.
|
|
1804
|
+
// When maxWidth is set, the outer TD stays at its normal width so it
|
|
1805
|
+
// always fills its parent — the inner maxWidth table (see below) does
|
|
1806
|
+
// the actual capping.
|
|
1804
1807
|
const outerTdStyle = {
|
|
1805
1808
|
width: config.width,
|
|
1806
1809
|
height: config.height,
|
|
@@ -1844,6 +1847,18 @@ function Column({ children, config, devNode }) {
|
|
|
1844
1847
|
fontSize: "1px",
|
|
1845
1848
|
width: "100%",
|
|
1846
1849
|
};
|
|
1850
|
+
// 5. maxWidth constraining table style (modern clients).
|
|
1851
|
+
// The `width` HTML attribute on this table is what Outlook Classic
|
|
1852
|
+
// (Word engine) reads — it has no concept of max-width, but it does
|
|
1853
|
+
// honour the `width` attribute as a hard column cap.
|
|
1854
|
+
// The CSS max-width here handles modern web/email clients correctly.
|
|
1855
|
+
// <center> around it ensures the constrained block stays horizontally
|
|
1856
|
+
// centred in both the Word engine and standards-based renderers.
|
|
1857
|
+
const maxWidthTableStyle = {
|
|
1858
|
+
width: "100%",
|
|
1859
|
+
maxWidth: config.maxWidth,
|
|
1860
|
+
borderCollapse: "collapse",
|
|
1861
|
+
};
|
|
1847
1862
|
// Main content rendering
|
|
1848
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", children: config.gap && numChildren > 1 ? (jsx("table", { "aria-label": "Column Gap Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1849
1864
|
width: "100%",
|
|
@@ -1860,7 +1875,24 @@ function Column({ children, config, devNode }) {
|
|
|
1860
1875
|
return (jsxs("table", { "aria-label": "Column Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
1861
1876
|
position: "relative",
|
|
1862
1877
|
...outerTableStyle,
|
|
1863
|
-
}, ...(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:
|
|
1878
|
+
}, ...(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 ? (
|
|
1879
|
+
/*
|
|
1880
|
+
* maxWidth wrapper — Outlook Classic compatibility pattern:
|
|
1881
|
+
*
|
|
1882
|
+
* <center> instructs the Word rendering engine to horizontally
|
|
1883
|
+
* centre its child block, equivalent to margin: 0 auto in CSS.
|
|
1884
|
+
*
|
|
1885
|
+
* The inner table carries the `width` HTML attribute set to the
|
|
1886
|
+
* maxWidth value. Outlook Classic reads `width` as a hard pixel
|
|
1887
|
+
* cap; it has no concept of max-width so this is the only lever
|
|
1888
|
+
* available. Modern clients receive the CSS max-width on the
|
|
1889
|
+
* same table and behave correctly.
|
|
1890
|
+
*
|
|
1891
|
+
* The outer column remains at its normal width so it always
|
|
1892
|
+
* fills its parent cell in every client — only the inner
|
|
1893
|
+
* content is capped.
|
|
1894
|
+
*/
|
|
1895
|
+
jsx("center", { children: jsx("table", { "aria-label": "Column Max Width Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, width: config.maxWidth, style: maxWidthTableStyle, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { children: renderContent() }) }) }) }) })) : (renderContent()) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
1864
1896
|
}
|
|
1865
1897
|
var Column_default = memo(Column, arePropsEqual);
|
|
1866
1898
|
|
|
@@ -2192,36 +2224,7 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
|
|
|
2192
2224
|
mso-line-height-rule: exactly;
|
|
2193
2225
|
}
|
|
2194
2226
|
}
|
|
2195
|
-
|
|
2196
|
-
.row-content-table[data-mobile-justify="center"] { margin: 0 auto !important; float: none !important; }
|
|
2197
|
-
.row-content-table[data-mobile-justify="start"] { margin: 0 !important; float: left !important; }
|
|
2198
|
-
.row-content-table[data-mobile-justify="end"] { margin: 0 0 0 auto !important; float: right !important; }
|
|
2199
|
-
.row-content-table[data-mobile-align="center"] .child-cell { vertical-align: middle !important; }
|
|
2200
|
-
.row-content-table[data-mobile-align="start"] .child-cell { vertical-align: top !important; }
|
|
2201
|
-
.row-content-table[data-mobile-align="end"] .child-cell { vertical-align: bottom !important; }
|
|
2202
|
-
.row-content-table[data-mobile-wrap="true"] { width: 100% !important; max-width: 100% !important; }
|
|
2203
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr { display: block !important; }
|
|
2204
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell {
|
|
2205
|
-
display: block !important;
|
|
2206
|
-
width: 100% !important;
|
|
2207
|
-
box-sizing: border-box !important;
|
|
2208
|
-
}
|
|
2209
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .row-gap-td {
|
|
2210
|
-
display: none !important;
|
|
2211
|
-
width: 0 !important;
|
|
2212
|
-
height: 0 !important;
|
|
2213
|
-
}
|
|
2214
|
-
.row-content-table[data-mobile-wrap="true"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2215
|
-
margin-bottom: 20px !important;
|
|
2216
|
-
}
|
|
2217
|
-
${["10px", "15px", "20px", "24px", "30px", "40px", ...rowGaps]
|
|
2218
|
-
.filter((gap, index, self) => self.indexOf(gap) === index)
|
|
2219
|
-
.map((gap) => `
|
|
2220
|
-
.row-content-table[data-mobile-wrap="true"][data-gap="${gap}"] > tbody > .content-tr > .child-cell:not(:last-child) {
|
|
2221
|
-
margin-bottom: ${gap} !important;
|
|
2222
|
-
}`)
|
|
2223
|
-
.join("\n")}
|
|
2224
|
-
}
|
|
2227
|
+
|
|
2225
2228
|
a { color: inherit; text-decoration: none; }
|
|
2226
2229
|
ol, ul { margin: 0px; padding: 0px; list-style: none; }
|
|
2227
2230
|
li {
|
|
@@ -2373,7 +2376,9 @@ function resolveAnchorStyles(anchor, fallback) {
|
|
|
2373
2376
|
else if (fallback === null || fallback === void 0 ? void 0 : fallback[prop]) {
|
|
2374
2377
|
resolved[prop] = fallback[prop];
|
|
2375
2378
|
}
|
|
2376
|
-
|
|
2379
|
+
else if (prop === "text-decoration") {
|
|
2380
|
+
resolved[prop] = "none";
|
|
2381
|
+
}
|
|
2377
2382
|
}
|
|
2378
2383
|
return Object.entries(resolved)
|
|
2379
2384
|
.map(([k, v]) => `${k}:${v}`)
|
|
@@ -2713,11 +2718,16 @@ function getHrefFromInnerLink(innerLink) {
|
|
|
2713
2718
|
}
|
|
2714
2719
|
}
|
|
2715
2720
|
function Row({ children, config, devNode, devMode }) {
|
|
2716
|
-
var _a, _b, _c, _d, _e, _f
|
|
2721
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2717
2722
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2718
2723
|
const numChildren = childrenArray.length;
|
|
2719
2724
|
const href = getHrefFromInnerLink(config.innerLink);
|
|
2720
2725
|
const target = ((_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target) || "_blank";
|
|
2726
|
+
// Whether children should stack on mobile.
|
|
2727
|
+
// Mirrors Container's isStacking pattern: drives stack-td / desktop-gap-column
|
|
2728
|
+
// / mobile-gap-spacer class names so that stacking works via non-@media CSS
|
|
2729
|
+
// rules that survive Gmail's stylesheet stripping.
|
|
2730
|
+
const isStacking = ((_b = config.mobile) === null || _b === void 0 ? void 0 : _b.wrap) === true && numChildren > 1;
|
|
2721
2731
|
// 1. Outer TD: Background, Border Radius, Width, Height.
|
|
2722
2732
|
const backgroundTdStyle = {
|
|
2723
2733
|
backgroundColor: config.backgroundColor,
|
|
@@ -2727,9 +2737,9 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2727
2737
|
backgroundImage: config.backgroundImage
|
|
2728
2738
|
? `url(${config.backgroundImage.src})`
|
|
2729
2739
|
: undefined,
|
|
2730
|
-
backgroundRepeat: (
|
|
2731
|
-
backgroundSize: (
|
|
2732
|
-
backgroundPosition: (
|
|
2740
|
+
backgroundRepeat: (_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.repeat,
|
|
2741
|
+
backgroundSize: (_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.size,
|
|
2742
|
+
backgroundPosition: (_e = config.backgroundImage) === null || _e === void 0 ? void 0 : _e.position,
|
|
2733
2743
|
...(config.borderRadius && { overflow: "hidden" }),
|
|
2734
2744
|
};
|
|
2735
2745
|
// 2. Inner Table: Border and Border Radius.
|
|
@@ -2784,13 +2794,30 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2784
2794
|
width: "100%",
|
|
2785
2795
|
height: "100%",
|
|
2786
2796
|
borderCollapse: "collapse",
|
|
2787
|
-
}, 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-
|
|
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) => (jsxs(Fragment, { children: [jsxs("td", { align: tdAlign, style: {
|
|
2788
2798
|
verticalAlign: tdValign,
|
|
2789
|
-
textAlign:
|
|
2799
|
+
textAlign: tdAlign,
|
|
2790
2800
|
padding: "0",
|
|
2791
2801
|
margin: "0",
|
|
2792
|
-
},
|
|
2793
|
-
|
|
2802
|
+
},
|
|
2803
|
+
// Mirror of Container's stack-td pattern: when isStacking,
|
|
2804
|
+
// the non-@media .stack-td rule forces display:block +
|
|
2805
|
+
// width:100% on each child, which survives Gmail's
|
|
2806
|
+
// @media stripping and achieves true mobile stacking.
|
|
2807
|
+
className: `child-cell${isStacking ? " stack-td" : ""}`, children: [child, isStacking &&
|
|
2808
|
+
index < numChildren - 1 &&
|
|
2809
|
+
config.gap && (jsx("div", { className: "mobile-gap-spacer", style: {
|
|
2810
|
+
display: "none",
|
|
2811
|
+
fontSize: "0",
|
|
2812
|
+
lineHeight: "0",
|
|
2813
|
+
height: config.gap,
|
|
2814
|
+
}, children: "\u00A0" }))] }), index < numChildren - 1 &&
|
|
2815
|
+
config.gap && (jsx("td", { width: config.gap, style: gapTdStyle,
|
|
2816
|
+
// Mirror of Container's desktop-gap-column pattern:
|
|
2817
|
+
// when isStacking, the non-@media .desktop-gap-column
|
|
2818
|
+
// rule collapses the between-column gap td so it does
|
|
2819
|
+
// not create phantom space while children are stacked.
|
|
2820
|
+
className: `row-gap-td${isStacking ? " desktop-gap-column" : ""}`, children: "\u00A0" }, `row-gap-${index}`))] }, `row-child-${index}`))) }) }) }) }) }) }) }) }) }) }) }) }) }) }), devNode && (jsx("tfoot", { children: jsx("tr", { children: jsx("td", { children: devNode }) }) }))] }));
|
|
2794
2821
|
if (href && !devMode) {
|
|
2795
2822
|
return (jsx("a", { href: href, ...({ target }), style: {
|
|
2796
2823
|
textDecoration: "none",
|
|
@@ -2906,13 +2933,19 @@ var Spacer_default = memo(Spacer, arePropsEqual);
|
|
|
2906
2933
|
function Text({ config, devMode, children }) {
|
|
2907
2934
|
const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth, } = config;
|
|
2908
2935
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
2936
|
+
// When maxWidth is set, this TD stays at width: 100% so it always fills
|
|
2937
|
+
// its parent — the inner maxWidth table (see below) does the actual
|
|
2938
|
+
// capping, keeping the outer layout intact in all clients.
|
|
2909
2939
|
const tdStyle = {
|
|
2910
2940
|
padding: padding,
|
|
2911
2941
|
backgroundColor: backgroundColor,
|
|
2912
2942
|
width: "100%",
|
|
2913
2943
|
verticalAlign: "top",
|
|
2914
2944
|
};
|
|
2915
|
-
// 2. Content Style: Applied directly to
|
|
2945
|
+
// 2. Content Style: Applied directly to the inner div wrapper.
|
|
2946
|
+
// maxWidth is intentionally omitted here — putting it on a div has no
|
|
2947
|
+
// effect in Outlook Classic (Word engine ignores CSS on div elements).
|
|
2948
|
+
// The constraint is enforced at the table level instead (see below).
|
|
2916
2949
|
const contentStyle = {
|
|
2917
2950
|
color: color,
|
|
2918
2951
|
textAlign: textAlign,
|
|
@@ -2931,7 +2964,18 @@ function Text({ config, devMode, children }) {
|
|
|
2931
2964
|
wordBreak: wordBreak,
|
|
2932
2965
|
margin: "0",
|
|
2933
2966
|
padding: "0",
|
|
2934
|
-
|
|
2967
|
+
};
|
|
2968
|
+
// 3. maxWidth constraining table style (modern clients).
|
|
2969
|
+
// The `width` HTML attribute on this table is what Outlook Classic
|
|
2970
|
+
// (Word engine) reads — it has no concept of max-width, but it does
|
|
2971
|
+
// honour the `width` attribute as a hard column cap.
|
|
2972
|
+
// The CSS max-width here handles modern web/email clients correctly.
|
|
2973
|
+
// <center> around it ensures the constrained block stays horizontally
|
|
2974
|
+
// centred in both the Word engine and standards-based renderers.
|
|
2975
|
+
const maxWidthTableStyle = {
|
|
2976
|
+
width: "100%",
|
|
2977
|
+
maxWidth: maxWidth,
|
|
2978
|
+
borderCollapse: "collapse",
|
|
2935
2979
|
};
|
|
2936
2980
|
// Determine content to render
|
|
2937
2981
|
const content = text !== null && text !== void 0 ? text : children;
|
|
@@ -2939,10 +2983,27 @@ function Text({ config, devMode, children }) {
|
|
|
2939
2983
|
const processedHtml = isString
|
|
2940
2984
|
? injectLinkStyles(content, contentStyle)
|
|
2941
2985
|
: "";
|
|
2986
|
+
const innerContent = isString ? (jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsx("div", { style: contentStyle, children: content }));
|
|
2942
2987
|
return (jsx("table", { "aria-label": "Text Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2943
2988
|
width: "100%",
|
|
2944
2989
|
borderCollapse: "collapse",
|
|
2945
|
-
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children:
|
|
2990
|
+
}, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children: maxWidth ? (
|
|
2991
|
+
/*
|
|
2992
|
+
* maxWidth wrapper — Outlook Classic compatibility pattern:
|
|
2993
|
+
*
|
|
2994
|
+
* <center> instructs the Word rendering engine to horizontally
|
|
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) }) }) }) }));
|
|
2946
3007
|
}
|
|
2947
3008
|
var Text_default = memo(Text, arePropsEqual);
|
|
2948
3009
|
|