@pagenflow/email 1.4.3 → 1.4.5
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 +7 -2
- package/dist/components/Column.d.ts +1 -1
- package/dist/components/Container.d.ts +1 -1
- package/dist/components/Divider.d.ts +0 -5
- package/dist/components/Image.d.ts +13 -0
- package/dist/components/Row.d.ts +1 -1
- package/dist/components/Section.d.ts +1 -1
- package/dist/components/Text.d.ts +2 -1
- package/dist/index.cjs.js +183 -88
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +183 -88
- package/dist/index.esm.js.map +1 -1
- package/dist/types/IInnerLink.d.ts +17 -0
- package/package.json +1 -1
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
import { BorderConfig } from "../types";
|
|
3
|
+
import IInnerLink from "../types/IInnerLink";
|
|
3
4
|
export interface ButtonConfig {
|
|
4
|
-
/**
|
|
5
|
-
|
|
5
|
+
/** Link configuration for the button destination. Required. */
|
|
6
|
+
innerLink?: IInnerLink;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Use innerLink property instead
|
|
9
|
+
*/
|
|
10
|
+
href?: string;
|
|
6
11
|
/** Button text. */
|
|
7
12
|
children: ReactNode;
|
|
8
13
|
/** Background color. Required for VML compatibility. */
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
export interface DividerConfig {
|
|
3
|
-
/** Thickness of the line (e.g., "1px"). */
|
|
4
3
|
height?: string;
|
|
5
|
-
/** Color of the line. */
|
|
6
4
|
color?: string;
|
|
7
|
-
/** Width of the line (e.g., "100%" or "300px"). */
|
|
8
5
|
width?: string;
|
|
9
|
-
/** Spacing above and below the divider (e.g., "20px 0"). */
|
|
10
6
|
margin?: string;
|
|
11
|
-
/** Horizontal alignment of the divider. */
|
|
12
7
|
align?: "left" | "center" | "right";
|
|
13
8
|
hideOnMobile?: boolean;
|
|
14
9
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import { BorderConfig } from "../types";
|
|
3
|
+
import IInnerLink from "../types/IInnerLink";
|
|
4
|
+
/**
|
|
5
|
+
* RULES NOT TO BE REMOVED
|
|
6
|
+
* -------------------
|
|
7
|
+
* - Image should not be draggable in dev mode as we don't want to disrupt the builder dnd behavior
|
|
8
|
+
*/
|
|
3
9
|
export interface ImageMobileConfig {
|
|
4
10
|
width?: string;
|
|
5
11
|
height?: string;
|
|
@@ -24,7 +30,14 @@ export interface ImageConfig {
|
|
|
24
30
|
padding?: string;
|
|
25
31
|
borderRadius?: string;
|
|
26
32
|
border?: BorderConfig;
|
|
33
|
+
innerLink?: IInnerLink;
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated Use innerLink property instead
|
|
36
|
+
*/
|
|
27
37
|
href?: string;
|
|
38
|
+
/**
|
|
39
|
+
* @deprecated Use innerLink property instead
|
|
40
|
+
*/
|
|
28
41
|
target?: string;
|
|
29
42
|
objectFit?: CSSProperties["objectFit"];
|
|
30
43
|
objectPosition?: string;
|
package/dist/components/Row.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface TextConfig {
|
|
|
17
17
|
/** Font style (e.g., 'italic'). */
|
|
18
18
|
fontStyle?: string;
|
|
19
19
|
/** Line height (e.g., '1.5' or '24px'). */
|
|
20
|
-
lineHeight?: string;
|
|
20
|
+
lineHeight?: string | number;
|
|
21
21
|
/** Letter spacing (e.g., '0.5px', '1px'). */
|
|
22
22
|
letterSpacing?: string;
|
|
23
23
|
/** Text transform (e.g., 'uppercase', 'lowercase', 'capitalize'). */
|
|
@@ -37,6 +37,7 @@ export interface TextConfig {
|
|
|
37
37
|
/** Word break behavior (e.g., 'break-all', 'break-word', 'keep-all', 'normal'). */
|
|
38
38
|
wordBreak?: string;
|
|
39
39
|
maxWidth?: string;
|
|
40
|
+
listStyle?: string;
|
|
40
41
|
}
|
|
41
42
|
export type TextProps = {
|
|
42
43
|
config: TextConfig;
|
package/dist/index.cjs.js
CHANGED
|
@@ -1539,6 +1539,27 @@ const justifyMap$3 = {
|
|
|
1539
1539
|
center: "center",
|
|
1540
1540
|
end: "right",
|
|
1541
1541
|
};
|
|
1542
|
+
// Helper to build link href based on innerLink type (mirrors Icon component)
|
|
1543
|
+
function buildLinkHref$2(innerLink) {
|
|
1544
|
+
if (!innerLink || innerLink.type === "none")
|
|
1545
|
+
return null;
|
|
1546
|
+
switch (innerLink.type) {
|
|
1547
|
+
case "url":
|
|
1548
|
+
return innerLink.url || null;
|
|
1549
|
+
case "email":
|
|
1550
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
1551
|
+
case "phone":
|
|
1552
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
1553
|
+
case "anchor":
|
|
1554
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
1555
|
+
case "page_top":
|
|
1556
|
+
return "#top";
|
|
1557
|
+
case "page_bottom":
|
|
1558
|
+
return "#bottom";
|
|
1559
|
+
default:
|
|
1560
|
+
return null;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1542
1563
|
function getBorderStyleString$2(border) {
|
|
1543
1564
|
if (!border)
|
|
1544
1565
|
return "";
|
|
@@ -1574,8 +1595,10 @@ function getBorderStyleString$2(border) {
|
|
|
1574
1595
|
return styles.join(" ");
|
|
1575
1596
|
}
|
|
1576
1597
|
function Button({ config, devMode }) {
|
|
1577
|
-
const {
|
|
1578
|
-
|
|
1598
|
+
const { innerLink, children, backgroundColor, color, padding, borderRadius, border, width, maxWidth, justifyContent, textAlign, fontSize, fontWeight, fontStyle, fontFamily, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, opacity, whiteSpace, wordBreak, } = config;
|
|
1599
|
+
// Resolve href from innerLink
|
|
1600
|
+
const href = buildLinkHref$2(innerLink);
|
|
1601
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
1579
1602
|
// Sanitize fontFamily early so safeFontFamily is available for all paths below.
|
|
1580
1603
|
const safeFontFamily = fontFamily
|
|
1581
1604
|
? fontFamily.replace(/['"]/g, "")
|
|
@@ -1595,23 +1618,27 @@ function Button({ config, devMode }) {
|
|
|
1595
1618
|
// Check if width is percentage-based or not defined
|
|
1596
1619
|
const isPercentageWidth = !width || width.includes("%");
|
|
1597
1620
|
const useSimpleOutlookApproach = isPercentageWidth;
|
|
1598
|
-
const align = justifyMap$3[justifyContent];
|
|
1621
|
+
const align = justifyContent ? justifyMap$3[justifyContent] : undefined;
|
|
1599
1622
|
// --- VML Calculation and Code for Outlook Compatibility (Fixed Width Only) ---
|
|
1600
1623
|
let vmlButton = "";
|
|
1601
1624
|
if (!useSimpleOutlookApproach) {
|
|
1602
1625
|
// VML needs fixed pixel height. We estimate it based on padding and potential wrapping.
|
|
1603
|
-
const numericPadding =
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1626
|
+
const numericPadding = padding
|
|
1627
|
+
? parseInt(padding.split(" ")[0] || "12", 10)
|
|
1628
|
+
: 12;
|
|
1629
|
+
const numericFontSize = fontSize ? parseInt(fontSize, 10) : 0;
|
|
1630
|
+
const numericLineHeight = lineHeight
|
|
1631
|
+
? lineHeight.includes("px")
|
|
1632
|
+
? parseInt(lineHeight, 10)
|
|
1633
|
+
: numericFontSize * parseFloat(lineHeight)
|
|
1634
|
+
: numericFontSize;
|
|
1608
1635
|
// Trust user's explicit pixel width - no calculation needed
|
|
1609
1636
|
const vmlWidth = parseInt(width, 10);
|
|
1610
1637
|
// Calculate VML height - trust user's padding and let text wrap naturally
|
|
1611
1638
|
// VML v:textbox will handle text wrapping automatically
|
|
1612
1639
|
const textContent = typeof children === "string" ? children : "";
|
|
1613
1640
|
// Estimate number of lines based on text length and button width
|
|
1614
|
-
const horizontalPadding = padding.split(" ")[1]
|
|
1641
|
+
const horizontalPadding = (padding === null || padding === void 0 ? void 0 : padding.split(" ")[1])
|
|
1615
1642
|
? parseInt(padding.split(" ")[1], 10) * 2
|
|
1616
1643
|
: numericPadding * 2;
|
|
1617
1644
|
const availableTextWidth = vmlWidth - horizontalPadding;
|
|
@@ -1624,15 +1651,17 @@ function Button({ config, devMode }) {
|
|
|
1624
1651
|
// Add extra 4px buffer to prevent bottom cropping in VML
|
|
1625
1652
|
const vmlHeight = Math.max(numericPadding * 2 + textHeight + 4, 40);
|
|
1626
1653
|
// VML colors must use the full hex format (e.g., #000000)
|
|
1627
|
-
const vmlFillColor = backgroundColor
|
|
1628
|
-
? backgroundColor
|
|
1629
|
-
|
|
1654
|
+
const vmlFillColor = backgroundColor
|
|
1655
|
+
? backgroundColor.startsWith("#")
|
|
1656
|
+
? backgroundColor
|
|
1657
|
+
: `#${backgroundColor}`
|
|
1658
|
+
: undefined;
|
|
1630
1659
|
// VML stroke color for border
|
|
1631
1660
|
const vmlStrokeColor = (border === null || border === void 0 ? void 0 : border.color) || vmlFillColor;
|
|
1632
1661
|
const vmlStrokeWeight = (border === null || border === void 0 ? void 0 : border.width) ? parseInt(border.width, 10) : 0;
|
|
1633
1662
|
const hasVmlStroke = vmlStrokeWeight > 0;
|
|
1634
1663
|
// Build VML font styles - consistent with other rendering paths
|
|
1635
|
-
const vmlFontWeight = fontWeight
|
|
1664
|
+
const vmlFontWeight = fontWeight;
|
|
1636
1665
|
const vmlFontStyle = fontStyle === "italic" ? "font-style:italic;" : "";
|
|
1637
1666
|
const vmlLetterSpacing = letterSpacing
|
|
1638
1667
|
? `letter-spacing:${letterSpacing};`
|
|
@@ -1643,12 +1672,12 @@ function Button({ config, devMode }) {
|
|
|
1643
1672
|
const vmlTextDecoration = textDecoration && textDecoration !== "none"
|
|
1644
1673
|
? `text-decoration:${textDecoration};`
|
|
1645
1674
|
: "";
|
|
1646
|
-
const vmlWhiteSpace = whiteSpace
|
|
1675
|
+
const vmlWhiteSpace = whiteSpace ? `white-space:${whiteSpace};` : "";
|
|
1647
1676
|
const vmlDirection = direction ? `direction:${direction};` : "";
|
|
1648
1677
|
const vmlOpacity = opacity !== undefined ? `opacity:${opacity};` : "";
|
|
1649
1678
|
// VML code uses MSO conditional comments to render only in Outlook
|
|
1650
1679
|
// Use table with explicit MSO height for vertical centering
|
|
1651
|
-
const horizontalPaddingValue = padding.split(" ")[1]
|
|
1680
|
+
const horizontalPaddingValue = (padding === null || padding === void 0 ? void 0 : padding.split(" ")[1])
|
|
1652
1681
|
? parseInt(padding.split(" ")[1], 10)
|
|
1653
1682
|
: numericPadding;
|
|
1654
1683
|
// For VML, we need to use a table inside to properly apply padding and centering
|
|
@@ -1657,7 +1686,7 @@ function Button({ config, devMode }) {
|
|
|
1657
1686
|
if (textAlign === "center") {
|
|
1658
1687
|
vmlAlignAttr = 'align="center"';
|
|
1659
1688
|
}
|
|
1660
|
-
else {
|
|
1689
|
+
else if (textAlign) {
|
|
1661
1690
|
vmlAlignStyle = `text-align:${textAlign};`;
|
|
1662
1691
|
}
|
|
1663
1692
|
// Border radius is intentionally omitted (arcsize="0%") for Outlook Classic.
|
|
@@ -1665,12 +1694,12 @@ function Button({ config, devMode }) {
|
|
|
1665
1694
|
// is inconsistent, so we render sharp corners there instead.
|
|
1666
1695
|
vmlButton = `
|
|
1667
1696
|
<!--[if mso]>
|
|
1668
|
-
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="${href}" style="height:${vmlHeight}px;width:${vmlWidth}px;" arcsize="0%" strokecolor="${vmlStrokeColor}" ${hasVmlStroke ? `strokeweight="${vmlStrokeWeight}px"` : 'stroke="f"'} fillcolor="${vmlFillColor}">
|
|
1697
|
+
<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}"` : ""}>
|
|
1669
1698
|
<w:anchorlock/>
|
|
1670
1699
|
<v:textbox inset="${horizontalPaddingValue}px,${numericPadding}px,${horizontalPaddingValue}px,${numericPadding}px">
|
|
1671
1700
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse:collapse;">
|
|
1672
1701
|
<tr>
|
|
1673
|
-
<td ${vmlAlignAttr} valign="middle" style="${vmlAlignStyle}color:${color}
|
|
1702
|
+
<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;">
|
|
1674
1703
|
${typeof children === "string" ? children : ""}
|
|
1675
1704
|
</td>
|
|
1676
1705
|
</tr>
|
|
@@ -1694,10 +1723,10 @@ function Button({ config, devMode }) {
|
|
|
1694
1723
|
const textTransformProp = textTransform
|
|
1695
1724
|
? `text-transform: ${textTransform};`
|
|
1696
1725
|
: "";
|
|
1697
|
-
const whiteSpaceProp = whiteSpace
|
|
1726
|
+
const whiteSpaceProp = whiteSpace ? `white-space: ${whiteSpace};` : "";
|
|
1698
1727
|
const directionProp = direction ? `direction: ${direction};` : "";
|
|
1699
1728
|
const opacityProp = opacity !== undefined ? `opacity: ${opacity};` : "";
|
|
1700
|
-
const wordBreakProp = wordBreak
|
|
1729
|
+
const wordBreakProp = wordBreak ? `word-break: ${wordBreak};` : "";
|
|
1701
1730
|
// Border radius is intentionally omitted from the Outlook Classic table cell.
|
|
1702
1731
|
// Outlook Classic ignores border-radius on table cells anyway, and including it
|
|
1703
1732
|
// can cause unexpected rendering artifacts, so we explicitly leave it out.
|
|
@@ -1705,13 +1734,17 @@ function Button({ config, devMode }) {
|
|
|
1705
1734
|
<!--[if mso]>
|
|
1706
1735
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;">
|
|
1707
1736
|
<tr>
|
|
1708
|
-
<td align="${align}" style="padding: 0;">
|
|
1737
|
+
<td ${align ? `align="${align}"` : ""} style="padding: 0;">
|
|
1709
1738
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="${width || "auto"}" style="border-collapse: collapse;">
|
|
1710
1739
|
<tr>
|
|
1711
|
-
<td bgcolor="${backgroundColor}" align="${textAlign}" style="padding: ${padding}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1740
|
+
<td ${backgroundColor ? `bgcolor="${backgroundColor}"` : ""} ${textAlign ? `align="${textAlign}"` : ""} style="${padding ? `padding: ${padding};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${borderStyleString}">
|
|
1741
|
+
${href
|
|
1742
|
+
? `<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;">
|
|
1743
|
+
${typeof children === "string" ? children : ""}
|
|
1744
|
+
</a>`
|
|
1745
|
+
: `<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;">
|
|
1746
|
+
${typeof children === "string" ? children : ""}
|
|
1747
|
+
</span>`}
|
|
1715
1748
|
</td>
|
|
1716
1749
|
</tr>
|
|
1717
1750
|
</table>
|
|
@@ -1725,7 +1758,7 @@ function Button({ config, devMode }) {
|
|
|
1725
1758
|
// fontFamily uses the sanitized value so embedded quotes never break the
|
|
1726
1759
|
// style attribute string (which is always wrapped in double quotes).
|
|
1727
1760
|
const sharedTextStyles = [
|
|
1728
|
-
`color: ${color}
|
|
1761
|
+
color ? `color: ${color};` : "",
|
|
1729
1762
|
safeFontFamily ? `font-family: ${safeFontFamily};` : "",
|
|
1730
1763
|
fontSize ? `font-size: ${fontSize};` : "",
|
|
1731
1764
|
fontWeight ? `font-weight: ${fontWeight};` : "",
|
|
@@ -1738,7 +1771,7 @@ function Button({ config, devMode }) {
|
|
|
1738
1771
|
: "",
|
|
1739
1772
|
direction ? `direction: ${direction};` : "",
|
|
1740
1773
|
opacity !== undefined ? `opacity: ${opacity};` : "",
|
|
1741
|
-
whiteSpace
|
|
1774
|
+
whiteSpace ? `white-space: ${whiteSpace};` : "",
|
|
1742
1775
|
]
|
|
1743
1776
|
.filter(Boolean)
|
|
1744
1777
|
.join(" ");
|
|
@@ -1772,20 +1805,24 @@ function Button({ config, devMode }) {
|
|
|
1772
1805
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; width: 100%;">
|
|
1773
1806
|
<tbody>
|
|
1774
1807
|
<tr>
|
|
1775
|
-
<td style="background-color: ${backgroundTdStyle.backgroundColor}
|
|
1776
|
-
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; border-radius: ${borderRadius}
|
|
1808
|
+
<td style="${backgroundTdStyle.backgroundColor ? `background-color: ${backgroundTdStyle.backgroundColor};` : ""} ${backgroundTdStyle.borderRadius ? `border-radius: ${backgroundTdStyle.borderRadius};` : ""} width: ${backgroundTdStyle.width}; ${maxWidth ? `max-width: ${maxWidth};` : ""} ${borderRadius ? "overflow: hidden;" : ""}">
|
|
1809
|
+
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: separate; border-spacing: 0; ${borderRadius ? `border-radius: ${borderRadius};` : ""} width: 100%; ${borderStyleString}">
|
|
1777
1810
|
<tbody>
|
|
1778
1811
|
<tr>
|
|
1779
1812
|
<td style="padding: 0;">
|
|
1780
1813
|
${devMode
|
|
1781
|
-
? `<span style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; word-break: ${wordBreak}
|
|
1814
|
+
? `<span style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; ${wordBreak ? `word-break: ${wordBreak};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${padding ? `padding: ${padding};` : ""}">
|
|
1782
1815
|
${typeof children === "string" ? children : ""}
|
|
1783
1816
|
</span>`
|
|
1784
|
-
:
|
|
1785
|
-
|
|
1817
|
+
: href
|
|
1818
|
+
? `<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};` : ""}">
|
|
1819
|
+
<span>
|
|
1820
|
+
${typeof children === "string" ? children : ""}
|
|
1821
|
+
</span>
|
|
1822
|
+
</a>`
|
|
1823
|
+
: `<span style="${sharedTextStyles} ${textDecoration && textDecoration !== "none" ? "" : "text-decoration: none;"} display: block; ${wordBreak ? `word-break: ${wordBreak};` : ""} ${textAlign ? `text-align: ${textAlign};` : ""} ${padding ? `padding: ${padding};` : ""}">
|
|
1786
1824
|
${typeof children === "string" ? children : ""}
|
|
1787
|
-
</span
|
|
1788
|
-
</a>`}
|
|
1825
|
+
</span>`}
|
|
1789
1826
|
</td>
|
|
1790
1827
|
</tr>
|
|
1791
1828
|
</tbody>
|
|
@@ -2104,40 +2141,48 @@ var Container_default = React.memo(Container, arePropsEqual);
|
|
|
2104
2141
|
|
|
2105
2142
|
function Divider({ config, devNode }) {
|
|
2106
2143
|
const { height = "1px", color = "#cccccc", width = "100%", margin = "20px 0", align = "center", hideOnMobile, } = config;
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
//
|
|
2115
|
-
const
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
backgroundColor: color,
|
|
2119
|
-
borderCollapse: "collapse",
|
|
2120
|
-
border: "0",
|
|
2121
|
-
// ✅ FIX 1: Use string literal indexing for MSO properties
|
|
2122
|
-
// ["mso-table-lspace" as string]: "0pt",
|
|
2123
|
-
["msoTableLspace"]: "0pt",
|
|
2124
|
-
// ["mso-table-rspace" as string]: "0pt",
|
|
2125
|
-
["msoTableRspace"]: "0pt",
|
|
2126
|
-
};
|
|
2127
|
-
// Parse height for the HTML attribute
|
|
2128
|
-
const dividerHeightAttribute = parseInt(height, 10) || 1;
|
|
2129
|
-
return (jsxRuntime.jsxs("table", { "aria-label": "Divider Wrapper", role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2130
|
-
// --- Start dev
|
|
2131
|
-
position: "relative",
|
|
2132
|
-
// --- End dev
|
|
2144
|
+
const heightPx = parseInt(height, 10) || 1;
|
|
2145
|
+
// Parse margin into paddingTop / paddingBottom for the outer TD.
|
|
2146
|
+
// Outlook ignores shorthand "20px 0" on TDs — must be explicit.
|
|
2147
|
+
const [marginTopRaw = "0", marginRightRaw = "0", marginBottomRaw, marginLeftRaw] = margin.trim().split(/\s+/);
|
|
2148
|
+
const marginTop = marginTopRaw;
|
|
2149
|
+
const marginBottom = marginBottomRaw !== null && marginBottomRaw !== void 0 ? marginBottomRaw : marginTopRaw; // "20px 0" → top=20px, bottom=20px
|
|
2150
|
+
// Outlook requires align on the outer TD to correctly position
|
|
2151
|
+
// a fixed-width inner table (e.g. width="300px").
|
|
2152
|
+
const alignAttr = align === "left" ? "left" : align === "right" ? "right" : "center";
|
|
2153
|
+
return (jsxRuntime.jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, style: {
|
|
2154
|
+
position: "relative", // dev overlay anchor
|
|
2133
2155
|
width: "100%",
|
|
2134
2156
|
borderCollapse: "collapse",
|
|
2135
|
-
|
|
2157
|
+
border: "0",
|
|
2158
|
+
}, className: hideOnMobile ? "hide-on-mobile" : undefined, children: [jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { align: alignAttr, style: {
|
|
2159
|
+
paddingTop: marginTop,
|
|
2160
|
+
paddingBottom: marginBottom,
|
|
2161
|
+
paddingLeft: "0",
|
|
2162
|
+
paddingRight: "0",
|
|
2163
|
+
fontSize: "0",
|
|
2164
|
+
lineHeight: "0",
|
|
2165
|
+
}, children: jsxRuntime.jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, align: alignAttr, style: {
|
|
2166
|
+
width: width,
|
|
2167
|
+
borderCollapse: "collapse",
|
|
2168
|
+
border: "0",
|
|
2169
|
+
}, children: jsxRuntime.jsx("tbody", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { ...{ height: heightPx }, ref: (el) => {
|
|
2170
|
+
if (!el)
|
|
2171
|
+
return;
|
|
2172
|
+
el.setAttribute("style", `height:${height};` +
|
|
2173
|
+
`line-height:${height};` +
|
|
2174
|
+
`font-size:0;` +
|
|
2175
|
+
`padding:0;` +
|
|
2176
|
+
`background-color:${color};` +
|
|
2177
|
+
`mso-line-height-rule:exactly;`);
|
|
2178
|
+
}, style: {
|
|
2179
|
+
// Fallback for non-Outlook clients (React-rendered style object).
|
|
2136
2180
|
height: height,
|
|
2181
|
+
lineHeight: height,
|
|
2137
2182
|
fontSize: "0",
|
|
2138
|
-
lineHeight: "0",
|
|
2139
2183
|
padding: "0",
|
|
2140
|
-
|
|
2184
|
+
backgroundColor: color,
|
|
2185
|
+
} }) }) }) }) }) }) }), devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] }));
|
|
2141
2186
|
}
|
|
2142
2187
|
var Divider_default = React.memo(Divider, arePropsEqual);
|
|
2143
2188
|
|
|
@@ -2382,6 +2427,27 @@ function Html({ children, backgroundColor = "#ffffff", }) {
|
|
|
2382
2427
|
);
|
|
2383
2428
|
}
|
|
2384
2429
|
|
|
2430
|
+
// Helper to build link href based on innerLink type
|
|
2431
|
+
function buildLinkHref$1(innerLink) {
|
|
2432
|
+
if (!innerLink || innerLink.type === "none")
|
|
2433
|
+
return null;
|
|
2434
|
+
switch (innerLink.type) {
|
|
2435
|
+
case "url":
|
|
2436
|
+
return innerLink.url || null;
|
|
2437
|
+
case "email":
|
|
2438
|
+
return innerLink.email ? `mailto:${innerLink.email}` : null;
|
|
2439
|
+
case "phone":
|
|
2440
|
+
return innerLink.phone ? `tel:${innerLink.phone}` : null;
|
|
2441
|
+
case "anchor":
|
|
2442
|
+
return innerLink.anchor ? `#${innerLink.anchor}` : null;
|
|
2443
|
+
case "page_top":
|
|
2444
|
+
return "#top";
|
|
2445
|
+
case "page_bottom":
|
|
2446
|
+
return "#bottom";
|
|
2447
|
+
default:
|
|
2448
|
+
return null;
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2385
2451
|
function getBorderStyle$3(border) {
|
|
2386
2452
|
if (!border)
|
|
2387
2453
|
return {};
|
|
@@ -2424,7 +2490,10 @@ function getBorderStyleString$1(border) {
|
|
|
2424
2490
|
}
|
|
2425
2491
|
function Image({ config, devNode, devMode }) {
|
|
2426
2492
|
var _a, _b;
|
|
2427
|
-
const { src, alt,
|
|
2493
|
+
const { src, alt, innerLink, mobile } = config;
|
|
2494
|
+
// Resolve href and target from innerLink
|
|
2495
|
+
const href = buildLinkHref$1(innerLink);
|
|
2496
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2428
2497
|
const seed = src + (alt || "");
|
|
2429
2498
|
const instanceId = seed
|
|
2430
2499
|
.split("")
|
|
@@ -2454,32 +2523,56 @@ function Image({ config, devNode, devMode }) {
|
|
|
2454
2523
|
? parseInt(config.maxWidth, 10)
|
|
2455
2524
|
: undefined;
|
|
2456
2525
|
const imgWidthAttr = isPercent ? (maxWidthPx !== null && maxWidthPx !== void 0 ? maxWidthPx : undefined) : widthAttr;
|
|
2457
|
-
// 2. Mobile Overrides
|
|
2526
|
+
// 2. Mobile Overrides — only emit CSS properties that are explicitly set,
|
|
2527
|
+
// so unspecified properties are left untouched (no forced defaults).
|
|
2458
2528
|
let mobileCss = "";
|
|
2459
2529
|
if (mobile) {
|
|
2530
|
+
// .wrap-${imgClass} rules
|
|
2531
|
+
const wrapRules = [
|
|
2532
|
+
// Always reset min-width so the px lock from desktop can be overridden
|
|
2533
|
+
"min-width: 0 !important;",
|
|
2534
|
+
];
|
|
2535
|
+
if (mobile.width !== undefined)
|
|
2536
|
+
wrapRules.push(`width: ${mobile.width} !important;`);
|
|
2537
|
+
if (mobile.maxWidth !== undefined)
|
|
2538
|
+
wrapRules.push(`max-width: ${mobile.maxWidth} !important;`);
|
|
2539
|
+
// .td-${imgClass} rules
|
|
2540
|
+
const tdRules = [];
|
|
2541
|
+
if (mobile.padding !== undefined)
|
|
2542
|
+
tdRules.push(`padding: ${mobile.padding} !important;`);
|
|
2543
|
+
if (mobile.backgroundColor !== undefined)
|
|
2544
|
+
tdRules.push(`background-color: ${mobile.backgroundColor} !important;`);
|
|
2545
|
+
// .${imgClass} rules
|
|
2546
|
+
const imgRules = [];
|
|
2547
|
+
if (mobile.width !== undefined)
|
|
2548
|
+
imgRules.push(`width: ${mobile.width} !important;`);
|
|
2549
|
+
if (mobile.height !== undefined)
|
|
2550
|
+
imgRules.push(`height: ${mobile.height} !important;`);
|
|
2551
|
+
if (mobile.maxWidth !== undefined)
|
|
2552
|
+
imgRules.push(`max-width: ${mobile.maxWidth} !important;`);
|
|
2553
|
+
if (mobile.maxHeight !== undefined)
|
|
2554
|
+
imgRules.push(`max-height: ${mobile.maxHeight} !important;`);
|
|
2555
|
+
if (mobile.borderRadius !== undefined)
|
|
2556
|
+
imgRules.push(`border-radius: ${mobile.borderRadius} !important;`);
|
|
2557
|
+
if (mobile.hidden !== undefined)
|
|
2558
|
+
imgRules.push(`display: ${mobile.hidden ? "none" : "block"} !important;`);
|
|
2559
|
+
if (mobile.objectFit !== undefined)
|
|
2560
|
+
imgRules.push(`object-fit: ${mobile.objectFit} !important;`);
|
|
2561
|
+
if (mobile.objectPosition !== undefined)
|
|
2562
|
+
imgRules.push(`object-position: ${mobile.objectPosition} !important;`);
|
|
2563
|
+
if (mobile.border !== undefined)
|
|
2564
|
+
imgRules.push(getBorderStyleString$1(mobile.border));
|
|
2460
2565
|
mobileCss = `
|
|
2461
2566
|
@media screen and (max-width: 768px) {
|
|
2462
2567
|
.wrap-${imgClass} {
|
|
2463
2568
|
/* This breaks the px lock from desktop and makes it fluid */
|
|
2464
|
-
|
|
2465
|
-
max-width: ${mobile.maxWidth || "100%"} !important;
|
|
2466
|
-
min-width: 0 !important;
|
|
2569
|
+
${wrapRules.join("\n ")}
|
|
2467
2570
|
}
|
|
2468
2571
|
.td-${imgClass} {
|
|
2469
|
-
|
|
2470
|
-
background-color: ${mobile.backgroundColor || "transparent"} !important;
|
|
2471
|
-
width: 100% !important;
|
|
2572
|
+
${tdRules.join("\n ")}
|
|
2472
2573
|
}
|
|
2473
2574
|
.${imgClass} {
|
|
2474
|
-
|
|
2475
|
-
height: ${mobile.height || "auto"} !important;
|
|
2476
|
-
max-width: ${mobile.maxWidth || "100%"} !important;
|
|
2477
|
-
max-height: ${mobile.maxHeight || "none"} !important;
|
|
2478
|
-
border-radius: ${mobile.borderRadius || "0"} !important;
|
|
2479
|
-
display: ${mobile.hidden ? "none" : "block"} !important;
|
|
2480
|
-
object-fit: ${mobile.objectFit || "fill"} !important;
|
|
2481
|
-
object-position: ${mobile.objectPosition || "center"} !important;
|
|
2482
|
-
${getBorderStyleString$1(mobile.border)}
|
|
2575
|
+
${imgRules.join("\n ")}
|
|
2483
2576
|
}
|
|
2484
2577
|
}
|
|
2485
2578
|
`;
|
|
@@ -2497,7 +2590,7 @@ function Image({ config, devNode, devMode }) {
|
|
|
2497
2590
|
objectFit: config.objectFit,
|
|
2498
2591
|
objectPosition: config.objectPosition,
|
|
2499
2592
|
};
|
|
2500
|
-
const imageElement = (jsxRuntime.jsx("img", { src: src, alt: alt, width: imgWidthAttr, height: heightAttr !== "auto" ? heightAttr : undefined, className: imgClass, style: imgStyle }));
|
|
2593
|
+
const imageElement = (jsxRuntime.jsx("img", { src: src, alt: alt, width: imgWidthAttr, height: heightAttr !== "auto" ? heightAttr : undefined, className: imgClass, style: imgStyle, draggable: !devMode }));
|
|
2501
2594
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [mobile && jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: mobileCss } }), jsxRuntime.jsxs("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, border: 0, className: `wrap-${imgClass}`, align: "center" // Ensures a 300px image stays centered in its parent
|
|
2502
2595
|
, style: {
|
|
2503
2596
|
width: tableWidth, // Fixed px here prevents the 100% "ghost space"
|
|
@@ -2510,7 +2603,9 @@ function Image({ config, devNode, devMode }) {
|
|
|
2510
2603
|
fontSize: "0",
|
|
2511
2604
|
lineHeight: "0",
|
|
2512
2605
|
width: tableWidth, // Lock the cell as well
|
|
2513
|
-
}, children: href && !devMode ? (jsxRuntime.jsx("a", { href: href, target: target,
|
|
2606
|
+
}, children: href && !devMode ? (jsxRuntime.jsx("a", { href: href, target: target, ...(target === "_blank"
|
|
2607
|
+
? { rel: "noopener noreferrer" }
|
|
2608
|
+
: {}), style: { display: "block", width: "100%" }, children: imageElement })) : (imageElement) }) }) }), devMode && !!devNode && (jsxRuntime.jsx("tfoot", { children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { children: devNode }) }) }))] })] }));
|
|
2514
2609
|
}
|
|
2515
2610
|
var Image_default = React.memo(Image, arePropsEqual);
|
|
2516
2611
|
|
|
@@ -2584,7 +2679,7 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2584
2679
|
const childrenArray = (Array.isArray(children) ? children : [children]).filter((child) => child != null);
|
|
2585
2680
|
const numChildren = childrenArray.length;
|
|
2586
2681
|
const href = getHrefFromInnerLink(config.innerLink);
|
|
2587
|
-
const target = (_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target;
|
|
2682
|
+
const target = ((_a = config.innerLink) === null || _a === void 0 ? void 0 : _a.target) || "_blank";
|
|
2588
2683
|
// 1. Outer TD: Background, Border Radius, Width, Height.
|
|
2589
2684
|
const backgroundTdStyle = {
|
|
2590
2685
|
backgroundColor: config.backgroundColor,
|
|
@@ -2659,7 +2754,7 @@ function Row({ children, config, devNode, devMode }) {
|
|
|
2659
2754
|
}, className: "child-cell", children: child }), index < numChildren - 1 &&
|
|
2660
2755
|
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 }) }) }))] }));
|
|
2661
2756
|
if (href && !devMode) {
|
|
2662
|
-
return (jsxRuntime.jsx("a", { href: href, ...(
|
|
2757
|
+
return (jsxRuntime.jsx("a", { href: href, ...({ target }), style: {
|
|
2663
2758
|
textDecoration: "none",
|
|
2664
2759
|
color: "inherit",
|
|
2665
2760
|
display: "block",
|
|
@@ -2771,7 +2866,7 @@ function Spacer({ config, devNode }) {
|
|
|
2771
2866
|
var Spacer_default = React.memo(Spacer, arePropsEqual);
|
|
2772
2867
|
|
|
2773
2868
|
function Text({ config, devMode, children }) {
|
|
2774
|
-
const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth } = config;
|
|
2869
|
+
const { text, padding, color, textAlign, fontFamily, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform, textDecoration, direction, verticalAlign, backgroundColor, opacity, whiteSpace, wordBreak = "break-all", maxWidth, } = config;
|
|
2775
2870
|
// 1. TD Style: Where padding and background are reliably applied.
|
|
2776
2871
|
const tdStyle = {
|
|
2777
2872
|
padding: padding,
|
|
@@ -2798,7 +2893,7 @@ function Text({ config, devMode, children }) {
|
|
|
2798
2893
|
wordBreak: wordBreak,
|
|
2799
2894
|
margin: "0",
|
|
2800
2895
|
padding: "0",
|
|
2801
|
-
maxWidth
|
|
2896
|
+
maxWidth,
|
|
2802
2897
|
};
|
|
2803
2898
|
// Determine content to render
|
|
2804
2899
|
const content = text !== null && text !== void 0 ? text : children;
|
|
@@ -2905,7 +3000,7 @@ function buildIconifyUrl(config) {
|
|
|
2905
3000
|
const template = process.env.ICONIFY_API_IMAGE_URI ||
|
|
2906
3001
|
"https://iconify.pagenflow.com/api/image/{{height}}/{{color}}/{{rotate}}-{{rotate-orientation}}/{{icon-full-name}}.png";
|
|
2907
3002
|
return template
|
|
2908
|
-
.replace("{{height}}", String(numericHeight *
|
|
3003
|
+
.replace("{{height}}", String(numericHeight * 4))
|
|
2909
3004
|
.replace("{{color}}", cleanColor)
|
|
2910
3005
|
.replace("{{rotate}}", String(rotate))
|
|
2911
3006
|
.replace("{{rotate-orientation}}", rotateOrientation)
|
|
@@ -2939,7 +3034,7 @@ function Icon({ config, devNode, devMode, children }) {
|
|
|
2939
3034
|
// Determine icon source
|
|
2940
3035
|
const iconSrc = buildIconifyUrl(config);
|
|
2941
3036
|
const href = buildLinkHref(innerLink);
|
|
2942
|
-
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "
|
|
3037
|
+
const target = (innerLink === null || innerLink === void 0 ? void 0 : innerLink.target) || "_blank";
|
|
2943
3038
|
const align = justifyMap[justifyContent];
|
|
2944
3039
|
// Get border styles
|
|
2945
3040
|
const borderStyle = getBorderStyle(border);
|