@pagenflow/email 1.4.4 → 1.4.6

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.
Files changed (39) hide show
  1. package/dist/components/Button.d.ts +4 -0
  2. package/dist/components/Column.d.ts +1 -1
  3. package/dist/components/Container.d.ts +1 -1
  4. package/dist/components/Image.d.ts +8 -0
  5. package/dist/components/Row.d.ts +1 -1
  6. package/dist/components/Section.d.ts +1 -1
  7. package/dist/components/Text.d.ts +2 -1
  8. package/dist/components/utils/MiniDomParser.d.ts +23 -0
  9. package/dist/components/utils/injectLinkStyles.d.ts +1 -0
  10. package/dist/index.cjs.js +177 -132
  11. package/dist/index.cjs.js.map +1 -1
  12. package/dist/index.esm.js +177 -132
  13. package/dist/index.esm.js.map +1 -1
  14. package/dist/types/IInnerLink.d.ts +17 -0
  15. package/package.json +1 -1
  16. package/dist/components/Body.js +0 -57
  17. package/dist/components/BodyDev.js +0 -57
  18. package/dist/components/Button.js +0 -327
  19. package/dist/components/Column.js +0 -127
  20. package/dist/components/Container.js +0 -179
  21. package/dist/components/Divider.js +0 -41
  22. package/dist/components/Font.js +0 -44
  23. package/dist/components/Head.js +0 -134
  24. package/dist/components/HeadDev.js +0 -311
  25. package/dist/components/Heading.js +0 -46
  26. package/dist/components/Html.js +0 -20
  27. package/dist/components/Icon.js +0 -276
  28. package/dist/components/Image.js +0 -119
  29. package/dist/components/MsoConditional.js +0 -19
  30. package/dist/components/Row.js +0 -157
  31. package/dist/components/Section.js +0 -65
  32. package/dist/components/Spacer.js +0 -40
  33. package/dist/components/Text.js +0 -42
  34. package/dist/index.js +0 -17
  35. package/dist/types/IInnerLink.js +0 -1
  36. package/dist/types/ResolvedFont.js +0 -1
  37. package/dist/types/index.js +0 -1
  38. package/dist/utils/isEqual.js +0 -1439
  39. package/dist/utils/memoUtils.js +0 -55
package/dist/index.esm.js CHANGED
@@ -4,16 +4,16 @@ import React, { memo, Fragment } from 'react';
4
4
  function Body({ children, config = {} }) {
5
5
  var _a, _b, _c, _d;
6
6
  // Extract config values with fallbacks
7
- const globalColor = config.color || "#000000";
8
- const globalFontSize = config.fontSize || "16px";
9
- const globalBackgroundColor = config.backgroundColor || "#ffffff";
10
- const globalLineHeight = config.lineHeight || "1.4";
11
- const globalFontFamily = config.fontFamily || "Arial, Helvetica, sans-serif";
7
+ const globalColor = config.color || "";
8
+ const globalFontSize = config.fontSize || "";
9
+ const globalBackgroundColor = config.backgroundColor || "";
10
+ const globalLineHeight = config.lineHeight || "";
11
+ const globalFontFamily = config.fontFamily || "";
12
12
  // Background image properties
13
13
  const bgImage = ((_a = config.backgroundImage) === null || _a === void 0 ? void 0 : _a.src) || "";
14
- const bgRepeat = ((_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.repeat) || "no-repeat";
15
- const bgSize = ((_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size) || "cover";
16
- const bgPosition = ((_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position) || "center";
14
+ const bgRepeat = ((_b = config.backgroundImage) === null || _b === void 0 ? void 0 : _b.repeat) || "";
15
+ const bgSize = ((_c = config.backgroundImage) === null || _c === void 0 ? void 0 : _c.size) || "";
16
+ const bgPosition = ((_d = config.backgroundImage) === null || _d === void 0 ? void 0 : _d.position) || "";
17
17
  // 1. Style for the <body> tag inline
18
18
  const bodyStyle = {
19
19
  backgroundColor: globalBackgroundColor,
@@ -1612,133 +1612,40 @@ function Button({ config, devMode }) {
1612
1612
  };
1613
1613
  // Border styles
1614
1614
  const borderStyleString = getBorderStyleString$2(border);
1615
- // --- Determine Button Approach Based on Width ---
1616
- // Check if width is percentage-based or not defined
1617
- const isPercentageWidth = !width || width.includes("%");
1618
- const useSimpleOutlookApproach = isPercentageWidth;
1619
1615
  const align = justifyContent ? justifyMap$3[justifyContent] : undefined;
1620
- // --- VML Calculation and Code for Outlook Compatibility (Fixed Width Only) ---
1621
- let vmlButton = "";
1622
- if (!useSimpleOutlookApproach) {
1623
- // VML needs fixed pixel height. We estimate it based on padding and potential wrapping.
1624
- const numericPadding = padding ? parseInt(padding.split(" ")[0] || "12", 10) : 12;
1625
- const numericFontSize = fontSize ? parseInt(fontSize, 10) : 0;
1626
- const numericLineHeight = lineHeight
1627
- ? lineHeight.includes("px")
1628
- ? parseInt(lineHeight, 10)
1629
- : numericFontSize * parseFloat(lineHeight)
1630
- : numericFontSize;
1631
- // Trust user's explicit pixel width - no calculation needed
1632
- const vmlWidth = parseInt(width, 10);
1633
- // Calculate VML height - trust user's padding and let text wrap naturally
1634
- // VML v:textbox will handle text wrapping automatically
1635
- const textContent = typeof children === "string" ? children : "";
1636
- // Estimate number of lines based on text length and button width
1637
- const horizontalPadding = (padding === null || padding === void 0 ? void 0 : padding.split(" ")[1])
1638
- ? parseInt(padding.split(" ")[1], 10) * 2
1639
- : numericPadding * 2;
1640
- const availableTextWidth = vmlWidth - horizontalPadding;
1641
- const charWidthMultiplier = fontWeight && parseInt(fontWeight) >= 500 ? 0.7 : 0.6;
1642
- const avgCharWidth = numericFontSize * charWidthMultiplier;
1643
- const charsPerLine = Math.max(Math.floor(availableTextWidth / avgCharWidth), 1);
1644
- const numberOfLines = Math.max(Math.ceil(textContent.length / charsPerLine), 1);
1645
- // Calculate height: vertical padding + (lines * line height) + extra buffer for VML
1646
- const textHeight = numberOfLines * numericLineHeight;
1647
- // Add extra 4px buffer to prevent bottom cropping in VML
1648
- const vmlHeight = Math.max(numericPadding * 2 + textHeight + 4, 40);
1649
- // VML colors must use the full hex format (e.g., #000000)
1650
- const vmlFillColor = backgroundColor
1651
- ? backgroundColor.startsWith("#")
1652
- ? backgroundColor
1653
- : `#${backgroundColor}`
1654
- : undefined;
1655
- // VML stroke color for border
1656
- const vmlStrokeColor = (border === null || border === void 0 ? void 0 : border.color) || vmlFillColor;
1657
- const vmlStrokeWeight = (border === null || border === void 0 ? void 0 : border.width) ? parseInt(border.width, 10) : 0;
1658
- const hasVmlStroke = vmlStrokeWeight > 0;
1659
- // Build VML font styles - consistent with other rendering paths
1660
- const vmlFontWeight = fontWeight;
1661
- const vmlFontStyle = fontStyle === "italic" ? "font-style:italic;" : "";
1662
- const vmlLetterSpacing = letterSpacing
1663
- ? `letter-spacing:${letterSpacing};`
1664
- : "";
1665
- const vmlTextTransform = textTransform
1666
- ? `text-transform:${textTransform};`
1667
- : "";
1668
- const vmlTextDecoration = textDecoration && textDecoration !== "none"
1669
- ? `text-decoration:${textDecoration};`
1670
- : "";
1671
- const vmlWhiteSpace = whiteSpace ? `white-space:${whiteSpace};` : "";
1672
- const vmlDirection = direction ? `direction:${direction};` : "";
1673
- const vmlOpacity = opacity !== undefined ? `opacity:${opacity};` : "";
1674
- // VML code uses MSO conditional comments to render only in Outlook
1675
- // Use table with explicit MSO height for vertical centering
1676
- const horizontalPaddingValue = (padding === null || padding === void 0 ? void 0 : padding.split(" ")[1])
1677
- ? parseInt(padding.split(" ")[1], 10)
1678
- : numericPadding;
1679
- // For VML, we need to use a table inside to properly apply padding and centering
1680
- let vmlAlignAttr = "";
1681
- let vmlAlignStyle = "";
1682
- if (textAlign === "center") {
1683
- vmlAlignAttr = 'align="center"';
1684
- }
1685
- else if (textAlign) {
1686
- vmlAlignStyle = `text-align:${textAlign};`;
1687
- }
1688
- // Border radius is intentionally omitted (arcsize="0%") for Outlook Classic.
1689
- // Outlook Classic does not reliably support rounded corners and the result
1690
- // is inconsistent, so we render sharp corners there instead.
1691
- vmlButton = `
1692
- <!--[if mso]>
1693
- <v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" ${href ? `href="${href}"` : ""} style="height:${vmlHeight}px;width:${vmlWidth}px;" arcsize="0%" ${vmlStrokeColor ? `strokecolor="${vmlStrokeColor}"` : ""} ${hasVmlStroke ? `strokeweight="${vmlStrokeWeight}px"` : 'stroke="f"'} ${vmlFillColor ? `fillcolor="${vmlFillColor}"` : ""}>
1694
- <w:anchorlock/>
1695
- <v:textbox inset="${horizontalPaddingValue}px,${numericPadding}px,${horizontalPaddingValue}px,${numericPadding}px">
1696
- <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse:collapse;">
1697
- <tr>
1698
- <td ${vmlAlignAttr} valign="middle" style="${vmlAlignStyle}${color ? `color:${color};` : ""}${safeFontFamily ? `font-family:${safeFontFamily};` : ""}${fontSize ? `font-size:${fontSize};` : ""}${vmlFontWeight ? `font-weight:${vmlFontWeight};` : ""}${vmlFontStyle}${vmlLetterSpacing}${vmlTextTransform}${vmlTextDecoration}${vmlWhiteSpace}${vmlDirection}${vmlOpacity}${lineHeight ? `line-height:${lineHeight};` : ""}mso-line-height-rule:exactly;">
1699
- ${typeof children === "string" ? children : ""}
1700
- </td>
1701
- </tr>
1702
- </table>
1703
- </v:textbox>
1704
- </v:roundrect>
1705
- <![endif]-->
1706
- `;
1707
- }
1708
1616
  // --- Simple Outlook Approach for Percentage Widths ---
1709
1617
  let simpleOutlookButton = "";
1710
- if (useSimpleOutlookApproach) {
1711
- // Build consistent inline styles for text properties
1712
- const textDecorationStyle = textDecoration && textDecoration !== "none"
1713
- ? `text-decoration: ${textDecoration};`
1714
- : "";
1715
- const fontStyleProp = fontStyle ? `font-style: ${fontStyle};` : "";
1716
- const letterSpacingProp = letterSpacing
1717
- ? `letter-spacing: ${letterSpacing};`
1718
- : "";
1719
- const textTransformProp = textTransform
1720
- ? `text-transform: ${textTransform};`
1721
- : "";
1722
- const whiteSpaceProp = whiteSpace ? `white-space: ${whiteSpace};` : "";
1723
- const directionProp = direction ? `direction: ${direction};` : "";
1724
- const opacityProp = opacity !== undefined ? `opacity: ${opacity};` : "";
1725
- const wordBreakProp = wordBreak ? `word-break: ${wordBreak};` : "";
1726
- // Border radius is intentionally omitted from the Outlook Classic table cell.
1727
- // Outlook Classic ignores border-radius on table cells anyway, and including it
1728
- // can cause unexpected rendering artifacts, so we explicitly leave it out.
1729
- simpleOutlookButton = `
1618
+ // Build consistent inline styles for text properties
1619
+ const textDecorationStyle = textDecoration && textDecoration !== "none"
1620
+ ? `text-decoration: ${textDecoration};`
1621
+ : "";
1622
+ const fontStyleProp = fontStyle ? `font-style: ${fontStyle};` : "";
1623
+ const letterSpacingProp = letterSpacing
1624
+ ? `letter-spacing: ${letterSpacing};`
1625
+ : "";
1626
+ const textTransformProp = textTransform
1627
+ ? `text-transform: ${textTransform};`
1628
+ : "";
1629
+ const whiteSpaceProp = whiteSpace ? `white-space: ${whiteSpace};` : "";
1630
+ const directionProp = direction ? `direction: ${direction};` : "";
1631
+ const opacityProp = opacity !== undefined ? `opacity: ${opacity};` : "";
1632
+ const wordBreakProp = wordBreak ? `word-break: ${wordBreak};` : "";
1633
+ // Border radius is intentionally omitted from the Outlook Classic table cell.
1634
+ // Outlook Classic ignores border-radius on table cells anyway, and including it
1635
+ // can cause unexpected rendering artifacts, so we explicitly leave it out.
1636
+ simpleOutlookButton = `
1730
1637
  <!--[if mso]>
1731
1638
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;">
1732
1639
  <tr>
1733
1640
  <td ${align ? `align="${align}"` : ""} style="padding: 0;">
1734
1641
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="${width || "auto"}" style="border-collapse: collapse;">
1735
1642
  <tr>
1736
- <td ${backgroundColor ? `bgcolor="${backgroundColor}"` : ""} ${textAlign ? `align="${textAlign}"` : ""} style="${padding ? `padding: ${padding};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${borderStyleString}">
1643
+ <td ${backgroundColor ? `bgcolor="${backgroundColor}"` : ""} ${textAlign ? `align="${textAlign}"` : ""} style="${padding ? `padding: ${padding};` : ""} ${href ? "cursor: pointer;" : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${borderStyleString}">
1737
1644
  ${href
1738
- ? `<a href="${href}" target="${target}" rel="noopener noreferrer" style="${color ? `color: ${color};` : ""} ${textDecorationStyle} display: block; ${safeFontFamily ? `font-family: ${safeFontFamily};` : ""} ${fontSize ? `font-size: ${fontSize};` : ""} ${fontWeight ? `font-weight: ${fontWeight};` : ""} ${fontStyleProp} ${lineHeight ? `line-height: ${lineHeight};` : ""} ${letterSpacingProp} ${textTransformProp} ${textAlign ? `text-align: ${textAlign};` : ""} ${whiteSpaceProp} ${directionProp} ${opacityProp} ${wordBreakProp} mso-line-height-rule: exactly;">
1645
+ ? `<a href="${href}" target="${target}" rel="noopener noreferrer" style="${color ? `color: ${color};` : ""} ${textDecorationStyle} display: block; ${safeFontFamily ? `font-family: ${safeFontFamily};` : ""} ${fontSize ? `font-size: ${fontSize};` : ""} ${fontWeight ? `font-weight: ${fontWeight};` : ""} ${fontStyleProp} ${lineHeight ? `line-height: ${lineHeight};` : ""} ${letterSpacingProp} ${textTransformProp} ${textAlign ? `text-align: ${textAlign};` : ""} ${whiteSpaceProp} ${directionProp} ${opacityProp} ${wordBreakProp} mso-line-height-rule: exactly;">
1739
1646
  ${typeof children === "string" ? children : ""}
1740
1647
  </a>`
1741
- : `<span style="${color ? `color: ${color};` : ""} ${textDecorationStyle} display: block; ${safeFontFamily ? `font-family: ${safeFontFamily};` : ""} ${fontSize ? `font-size: ${fontSize};` : ""} ${fontWeight ? `font-weight: ${fontWeight};` : ""} ${fontStyleProp} ${lineHeight ? `line-height: ${lineHeight};` : ""} ${letterSpacingProp} ${textTransformProp} ${textAlign ? `text-align: ${textAlign};` : ""} ${whiteSpaceProp} ${directionProp} ${opacityProp} ${wordBreakProp} mso-line-height-rule: exactly;">
1648
+ : `<span style="${color ? `color: ${color};` : ""} ${textDecorationStyle} display: block; ${safeFontFamily ? `font-family: ${safeFontFamily};` : ""} ${fontSize ? `font-size: ${fontSize};` : ""} ${fontWeight ? `font-weight: ${fontWeight};` : ""} ${fontStyleProp} ${lineHeight ? `line-height: ${lineHeight};` : ""} ${letterSpacingProp} ${textTransformProp} ${textAlign ? `text-align: ${textAlign};` : ""} ${whiteSpaceProp} ${directionProp} ${opacityProp} ${wordBreakProp} mso-line-height-rule: exactly;">
1742
1649
  ${typeof children === "string" ? children : ""}
1743
1650
  </span>`}
1744
1651
  </td>
@@ -1749,7 +1656,6 @@ function Button({ config, devMode }) {
1749
1656
  </table>
1750
1657
  <![endif]-->
1751
1658
  `;
1752
- }
1753
1659
  // Build shared inline style fragments for the non-MSO path.
1754
1660
  // fontFamily uses the sanitized value so embedded quotes never break the
1755
1661
  // style attribute string (which is always wrapped in double quotes).
@@ -1796,7 +1702,7 @@ function Button({ config, devMode }) {
1796
1702
  padding: 0,
1797
1703
  }, onClick: devMode ? (e) => e.preventDefault() : undefined, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { dangerouslySetInnerHTML: {
1798
1704
  __html: `
1799
- ${useSimpleOutlookApproach ? simpleOutlookButton : vmlButton}
1705
+ ${simpleOutlookButton}
1800
1706
  <!--[if !mso]><!-->
1801
1707
  <table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
1802
1708
  <tbody>
@@ -1811,7 +1717,7 @@ function Button({ config, devMode }) {
1811
1717
  ${typeof children === "string" ? children : ""}
1812
1718
  </span>`
1813
1719
  : href
1814
- ? `<a href="${href}" target="${target}" rel="noopener noreferrer" style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; ${wordBreak ? `word-break: ${wordBreak};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${padding ? `padding: ${padding};` : ""}">
1720
+ ? `<a href="${href}" target="${target}" rel="noopener noreferrer" style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; cursor: pointer; ${wordBreak ? `word-break: ${wordBreak};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${padding ? `padding: ${padding};` : ""}">
1815
1721
  <span>
1816
1722
  ${typeof children === "string" ? children : ""}
1817
1723
  </span>
@@ -2359,6 +2265,139 @@ function Head({ children, backgroundColor = "#ffffff", title = "Email Preview",
2359
2265
  return (jsxs("head", { children: [jsx("meta", { httpEquiv: "Content-Type", content: "text/html; charset=utf-8" }), jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), jsx("meta", { httpEquiv: "X-UA-Compatible", content: "IE=edge" }), jsx("title", { children: title }), fonts.flatMap((resolved) => resolved.fontProps.map((props, i) => (jsx(Font, { ...props }, `${resolved.family}-${props.fontWeight}-${props.fontStyle}-${i}`)))), children, jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: msoResetStyles } }), jsx("style", { type: "text/css", dangerouslySetInnerHTML: { __html: globalStyles } })] }));
2360
2266
  }
2361
2267
 
2268
+ class MiniDomParser {
2269
+ constructor(html) {
2270
+ this.html = html;
2271
+ this.root = this.makeNode("root", {}, null);
2272
+ this.parse();
2273
+ }
2274
+ makeNode(tagName, attributes, parent) {
2275
+ var _a;
2276
+ return {
2277
+ tagName,
2278
+ attributes,
2279
+ style: this.parseStyle((_a = attributes["style"]) !== null && _a !== void 0 ? _a : ""),
2280
+ children: [],
2281
+ parent,
2282
+ rawHtml: "",
2283
+ };
2284
+ }
2285
+ parseStyle(styleStr) {
2286
+ const map = {};
2287
+ for (const declaration of styleStr.split(";")) {
2288
+ const [prop, ...rest] = declaration.split(":");
2289
+ if (!prop || !rest.length)
2290
+ continue;
2291
+ const key = prop.trim().toLowerCase();
2292
+ const val = rest.join(":").trim();
2293
+ if (key && val)
2294
+ map[key] = val;
2295
+ }
2296
+ return map;
2297
+ }
2298
+ parseAttributes(attrStr) {
2299
+ var _a, _b, _c;
2300
+ const attrs = {};
2301
+ const pattern = /(\w[\w-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+)))?/g;
2302
+ let m;
2303
+ while ((m = pattern.exec(attrStr)) !== null) {
2304
+ const key = m[1].toLowerCase();
2305
+ const val = (_c = (_b = (_a = m[2]) !== null && _a !== void 0 ? _a : m[3]) !== null && _b !== void 0 ? _b : m[4]) !== null && _c !== void 0 ? _c : "";
2306
+ attrs[key] = val;
2307
+ }
2308
+ return attrs;
2309
+ }
2310
+ parse() {
2311
+ const tokenPattern = /(<\/[\w]+\s*>|<[\w][^>]*>|[^<]+)/gi;
2312
+ const stack = [this.root];
2313
+ let m;
2314
+ while ((m = tokenPattern.exec(this.html)) !== null) {
2315
+ const token = m[0];
2316
+ if (token.startsWith("</")) {
2317
+ if (stack.length > 1)
2318
+ stack.pop();
2319
+ continue;
2320
+ }
2321
+ if (token.startsWith("<")) {
2322
+ const tagMatch = token.match(/^<([\w]+)([\s\S]*)>$/i);
2323
+ if (!tagMatch)
2324
+ continue;
2325
+ const tagName = tagMatch[1].toLowerCase();
2326
+ const attrStr = tagMatch[2].trim();
2327
+ const attrs = this.parseAttributes(attrStr);
2328
+ const current = stack[stack.length - 1];
2329
+ const node = this.makeNode(tagName, attrs, current);
2330
+ node.rawHtml = token;
2331
+ current.children.push(node);
2332
+ const selfClosing = /\/$/.test(attrStr) ||
2333
+ ["br", "hr", "img", "input", "meta", "link"].includes(tagName);
2334
+ if (!selfClosing)
2335
+ stack.push(node);
2336
+ }
2337
+ }
2338
+ }
2339
+ collectByTag(node, tag, results) {
2340
+ if (node.tagName === tag)
2341
+ results.push(node);
2342
+ for (const child of node.children) {
2343
+ this.collectByTag(child, tag, results);
2344
+ }
2345
+ }
2346
+ querySelectorAllByTag(tag) {
2347
+ const results = [];
2348
+ this.collectByTag(this.root, tag.toLowerCase(), results);
2349
+ return results;
2350
+ }
2351
+ }
2352
+
2353
+ function resolveInheritedStyle(node, prop) {
2354
+ let el = node.parent;
2355
+ while (el && el.tagName !== "root") {
2356
+ const val = el.style[prop];
2357
+ if (val && val !== "inherit")
2358
+ return val;
2359
+ el = el.parent;
2360
+ }
2361
+ return undefined;
2362
+ }
2363
+ const BROWSER_LINK_DEFAULTS = ["color", "text-decoration"];
2364
+ function resolveAnchorStyles(anchor, fallback) {
2365
+ const resolved = { ...anchor.style };
2366
+ for (const prop of BROWSER_LINK_DEFAULTS) {
2367
+ if (resolved[prop] && resolved[prop] !== "inherit")
2368
+ continue;
2369
+ const inherited = resolveInheritedStyle(anchor, prop);
2370
+ if (inherited) {
2371
+ resolved[prop] = inherited;
2372
+ }
2373
+ else if (fallback === null || fallback === void 0 ? void 0 : fallback[prop]) {
2374
+ resolved[prop] = fallback[prop];
2375
+ }
2376
+ // if neither — leave it out entirely, don't force inherit
2377
+ }
2378
+ return Object.entries(resolved)
2379
+ .map(([k, v]) => `${k}:${v}`)
2380
+ .join(";");
2381
+ }
2382
+ function injectLinkStyles(html, fallback) {
2383
+ if (!html || (!html.includes("<a ") && !html.includes("<a>")))
2384
+ return html;
2385
+ const parser = new MiniDomParser(html);
2386
+ const anchors = parser.querySelectorAllByTag("a");
2387
+ let result = html;
2388
+ for (const anchor of anchors) {
2389
+ const resolvedStyle = resolveAnchorStyles(anchor, fallback !== null && fallback !== void 0 ? fallback : {});
2390
+ const cleanAttrs = anchor.rawHtml
2391
+ .replace(/^<a\s*/i, "")
2392
+ .replace(/>$/, "")
2393
+ .replace(/style\s*=\s*(?:"[^"]*"|'[^']*')/gi, "")
2394
+ .trim();
2395
+ const newTag = `<a ${cleanAttrs} style="${resolvedStyle}">`.replace(/\s+/g, " ");
2396
+ result = result.replace(anchor.rawHtml, newTag);
2397
+ }
2398
+ return result;
2399
+ }
2400
+
2362
2401
  function Heading({ config, devMode, children }) {
2363
2402
  const { text, level = "h1", padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, wordBreak, whiteSpace, } = config;
2364
2403
  // Determine the content to render
@@ -2375,7 +2414,7 @@ function Heading({ config, devMode, children }) {
2375
2414
  const headingStyle = {
2376
2415
  color: color,
2377
2416
  textAlign: textAlign,
2378
- fontFamily: fontFamily || "Arial, Helvetica, sans-serif",
2417
+ fontFamily: fontFamily,
2379
2418
  fontSize: fontSize,
2380
2419
  fontWeight: fontWeight,
2381
2420
  fontStyle: fontStyle,
@@ -2392,6 +2431,9 @@ function Heading({ config, devMode, children }) {
2392
2431
  // Outlook specific fixes (using string indexing)
2393
2432
  ["msoLineHeightRule"]: "exactly",
2394
2433
  };
2434
+ const processedHtml = isString
2435
+ ? injectLinkStyles(content, headingStyle)
2436
+ : "";
2395
2437
  // Dynamically create the Heading element
2396
2438
  const HeadingTag = level;
2397
2439
  return (
@@ -2399,7 +2441,7 @@ function Heading({ config, devMode, children }) {
2399
2441
  jsx("table", { "aria-label": "Heading Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2400
2442
  width: "100%",
2401
2443
  borderCollapse: "collapse",
2402
- }, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children: isString ? (jsx(HeadingTag, { style: headingStyle, dangerouslySetInnerHTML: { __html: content } })) : (jsx(HeadingTag, { style: headingStyle, children: content })) }) }) }) }));
2444
+ }, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children: isString ? (jsx(HeadingTag, { style: headingStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsx(HeadingTag, { style: headingStyle, children: content })) }) }) }) }));
2403
2445
  }
2404
2446
  var Heading_default = memo(Heading, arePropsEqual);
2405
2447
 
@@ -2862,7 +2904,7 @@ function Spacer({ config, devNode }) {
2862
2904
  var Spacer_default = memo(Spacer, arePropsEqual);
2863
2905
 
2864
2906
  function Text({ config, devMode, children }) {
2865
- const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth } = config;
2907
+ const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth, } = config;
2866
2908
  // 1. TD Style: Where padding and background are reliably applied.
2867
2909
  const tdStyle = {
2868
2910
  padding: padding,
@@ -2874,7 +2916,7 @@ function Text({ config, devMode, children }) {
2874
2916
  const contentStyle = {
2875
2917
  color: color,
2876
2918
  textAlign: textAlign,
2877
- fontFamily: fontFamily || "Arial, Helvetica, sans-serif",
2919
+ fontFamily: fontFamily,
2878
2920
  fontSize: fontSize,
2879
2921
  fontWeight: fontWeight,
2880
2922
  fontStyle: fontStyle,
@@ -2889,15 +2931,18 @@ function Text({ config, devMode, children }) {
2889
2931
  wordBreak: wordBreak,
2890
2932
  margin: "0",
2891
2933
  padding: "0",
2892
- maxWidth
2934
+ maxWidth,
2893
2935
  };
2894
2936
  // Determine content to render
2895
2937
  const content = text !== null && text !== void 0 ? text : children;
2896
2938
  const isString = typeof content === "string";
2939
+ const processedHtml = isString
2940
+ ? injectLinkStyles(content, contentStyle)
2941
+ : "";
2897
2942
  return (jsx("table", { "aria-label": "Text Block Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
2898
2943
  width: "100%",
2899
2944
  borderCollapse: "collapse",
2900
- }, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children: isString ? (jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html: content } })) : (jsx("div", { style: contentStyle, children: content })) }) }) }) }));
2945
+ }, children: jsx("tbody", { children: jsx("tr", { children: jsx("td", { style: tdStyle, align: textAlign, children: isString ? (jsx("div", { style: contentStyle, dangerouslySetInnerHTML: { __html: processedHtml } })) : (jsx("div", { style: contentStyle, children: content })) }) }) }) }));
2901
2946
  }
2902
2947
  var Text_default = memo(Text, arePropsEqual);
2903
2948