@octanejs/email 0.0.13 → 0.0.14
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/package.json +4 -4
- package/src/components.tsrx +47 -40
- package/src/rich-content.tsrx +32 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octanejs/email",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
"tailwindcss": "4.3.3"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"octane": "^0.
|
|
45
|
+
"octane": "^0.11.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@react-email/components": "1.0.12",
|
|
49
49
|
"@react-email/render": "2.0.6",
|
|
50
|
-
"@tsrx/react": "^0.
|
|
50
|
+
"@tsrx/react": "^0.4.5",
|
|
51
51
|
"esbuild": "^0.28.1",
|
|
52
|
-
"octane": "0.
|
|
52
|
+
"octane": "0.11.0",
|
|
53
53
|
"react": "19.2.7",
|
|
54
54
|
"react-dom": "19.2.7",
|
|
55
55
|
"vitest": "^4.1.10"
|
package/src/components.tsrx
CHANGED
|
@@ -25,16 +25,14 @@ export function Body({ children, style = {}, ref, ...props }: BodyProps) @{
|
|
|
25
25
|
'paddingBottom',
|
|
26
26
|
'paddingLeft',
|
|
27
27
|
]) {
|
|
28
|
-
if ((style as Record<string, unknown>)[key] !== undefined)
|
|
29
|
-
string,
|
|
30
|
-
unknown
|
|
31
|
-
>)[key] = 0;
|
|
28
|
+
if ((style as Record<string, unknown>)[key] !== undefined)
|
|
29
|
+
(reset as Record<string, unknown>)[key] = 0;
|
|
32
30
|
}
|
|
33
31
|
<body
|
|
34
32
|
{...props}
|
|
35
33
|
{...withRef(ref)}
|
|
36
|
-
dir={props.dir as string | undefined ?? 'ltr'}
|
|
37
|
-
lang={props.lang as string | undefined ?? 'en'}
|
|
34
|
+
dir={(props.dir as string | undefined) ?? 'ltr'}
|
|
35
|
+
lang={(props.lang as string | undefined) ?? 'en'}
|
|
38
36
|
style={reset}
|
|
39
37
|
>
|
|
40
38
|
<table
|
|
@@ -48,10 +46,12 @@ export function Body({ children, style = {}, ref, ...props }: BodyProps) @{
|
|
|
48
46
|
<tbody>
|
|
49
47
|
<tr>
|
|
50
48
|
<td
|
|
51
|
-
dir={props.dir as string | undefined ?? 'ltr'}
|
|
52
|
-
lang={props.lang as string | undefined ?? 'en'}
|
|
49
|
+
dir={(props.dir as string | undefined) ?? 'ltr'}
|
|
50
|
+
lang={(props.lang as string | undefined) ?? 'en'}
|
|
53
51
|
style={style}
|
|
54
|
-
>
|
|
52
|
+
>
|
|
53
|
+
{children}
|
|
54
|
+
</td>
|
|
55
55
|
</tr>
|
|
56
56
|
</tbody>
|
|
57
57
|
</table>
|
|
@@ -60,7 +60,9 @@ export function Body({ children, style = {}, ref, ...props }: BodyProps) @{
|
|
|
60
60
|
|
|
61
61
|
export type HtmlProps = EmailElementProps<HTMLHtmlElement> & { lang?: string; dir?: string };
|
|
62
62
|
export function Html({ children, lang = 'en', dir = 'ltr', ref, ...props }: HtmlProps) @{
|
|
63
|
-
<html {...props} {...withRef(ref)} dir={dir} lang={lang}>
|
|
63
|
+
<html {...props} {...withRef(ref)} dir={dir} lang={lang}>
|
|
64
|
+
{children}
|
|
65
|
+
</html>
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
export type HeadProps = EmailElementProps<HTMLHeadElement>;
|
|
@@ -138,7 +140,9 @@ export function Row({ children, style, ref, ...props }: RowProps) @{
|
|
|
138
140
|
|
|
139
141
|
export type ColumnProps = EmailElementProps<HTMLTableCellElement>;
|
|
140
142
|
export function Column({ children, style, ref, ...props }: ColumnProps) @{
|
|
141
|
-
<td {...props} {...withRef(ref)} data-id="__react-email-column" style={style}>
|
|
143
|
+
<td {...props} {...withRef(ref)} data-id="__react-email-column" style={style}>
|
|
144
|
+
{children}
|
|
145
|
+
</td>
|
|
142
146
|
}
|
|
143
147
|
|
|
144
148
|
export type TextProps = EmailElementProps<HTMLParagraphElement>;
|
|
@@ -161,16 +165,17 @@ export function Link({ children, target = '_blank', style, ref, ...props }: Link
|
|
|
161
165
|
{...withRef(ref)}
|
|
162
166
|
style={{ color: '#067df7', textDecorationLine: 'none', ...style }}
|
|
163
167
|
target={target}
|
|
164
|
-
>
|
|
168
|
+
>
|
|
169
|
+
{children}
|
|
170
|
+
</a>
|
|
165
171
|
}
|
|
166
172
|
|
|
167
|
-
export type ImgProps =
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
};
|
|
173
|
+
export type ImgProps = EmailElementProps<HTMLImageElement> & {
|
|
174
|
+
alt?: string;
|
|
175
|
+
src?: string;
|
|
176
|
+
width?: string | number;
|
|
177
|
+
height?: string | number;
|
|
178
|
+
};
|
|
174
179
|
export function Img({ alt = '', src, width, height, style, ref, ...props }: ImgProps) @{
|
|
175
180
|
<img
|
|
176
181
|
{...props}
|
|
@@ -198,17 +203,16 @@ export function Hr({ style, ref, ...props }: HrProps) @{
|
|
|
198
203
|
/>
|
|
199
204
|
}
|
|
200
205
|
|
|
201
|
-
export type HeadingProps =
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
};
|
|
206
|
+
export type HeadingProps = EmailElementProps<HTMLHeadingElement> & {
|
|
207
|
+
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
208
|
+
m?: string | number;
|
|
209
|
+
mx?: string | number;
|
|
210
|
+
my?: string | number;
|
|
211
|
+
mt?: string | number;
|
|
212
|
+
mr?: string | number;
|
|
213
|
+
mb?: string | number;
|
|
214
|
+
ml?: string | number;
|
|
215
|
+
};
|
|
212
216
|
export function Heading({
|
|
213
217
|
as: Tag = 'h1',
|
|
214
218
|
children,
|
|
@@ -227,7 +231,9 @@ export function Heading({
|
|
|
227
231
|
{...props}
|
|
228
232
|
{...withRef(ref)}
|
|
229
233
|
style={{ ...withMargins({ m, mx, my, mt, mr, mb, ml }), ...style }}
|
|
230
|
-
>
|
|
234
|
+
>
|
|
235
|
+
{children}
|
|
236
|
+
</Tag>
|
|
231
237
|
}
|
|
232
238
|
|
|
233
239
|
export interface FontProps {
|
|
@@ -259,8 +265,8 @@ export function Font({
|
|
|
259
265
|
|
|
260
266
|
const PREVIEW_MAX_LENGTH = 200;
|
|
261
267
|
const WHITE_SPACE = ' ';
|
|
262
|
-
export type PreviewProps =
|
|
263
|
-
Readonly<
|
|
268
|
+
export type PreviewProps = Readonly<Omit<EmailElementProps<HTMLDivElement>, 'children'>> &
|
|
269
|
+
Readonly<{
|
|
264
270
|
text?: string;
|
|
265
271
|
children?: string | string[];
|
|
266
272
|
useTitleTag?: boolean;
|
|
@@ -272,12 +278,11 @@ export function Preview({
|
|
|
272
278
|
ref,
|
|
273
279
|
...props
|
|
274
280
|
}: PreviewProps) @{
|
|
275
|
-
const childText =
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
: '';
|
|
281
|
+
const childText = Array.isArray(children)
|
|
282
|
+
? children.join('')
|
|
283
|
+
: typeof children === 'string'
|
|
284
|
+
? children
|
|
285
|
+
: '';
|
|
281
286
|
const text = (explicitText ?? childText).substring(0, PREVIEW_MAX_LENGTH);
|
|
282
287
|
<>
|
|
283
288
|
@if (useTitleTag) {
|
|
@@ -316,7 +321,9 @@ export function CodeInline({ children, style, ref, ...props }: CodeInlineProps)
|
|
|
316
321
|
borderRadius: '4px',
|
|
317
322
|
...style,
|
|
318
323
|
}}
|
|
319
|
-
>
|
|
324
|
+
>
|
|
325
|
+
{children}
|
|
326
|
+
</code>
|
|
320
327
|
}
|
|
321
328
|
|
|
322
329
|
export type ButtonProps = EmailElementProps<HTMLAnchorElement> & { href?: string; target?: string };
|
package/src/rich-content.tsrx
CHANGED
|
@@ -13,14 +13,18 @@ function resolveTextChild(child: unknown): string {
|
|
|
13
13
|
}
|
|
14
14
|
if (typeof value === 'string') return value;
|
|
15
15
|
if (isChildrenBlock(child)) {
|
|
16
|
-
throw new Error(
|
|
17
|
-
'
|
|
16
|
+
throw new Error(
|
|
17
|
+
'Markdown children must be a string prop: use <Markdown children={"…"} />. ' +
|
|
18
|
+
'JSX children compile to a children block, which is not a string.',
|
|
19
|
+
);
|
|
18
20
|
}
|
|
19
21
|
throw new Error('Markdown children must resolve to a string');
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
export type MarkdownProps =
|
|
23
|
-
|
|
24
|
+
export type MarkdownProps = Readonly<
|
|
25
|
+
Omit<EmailElementProps<HTMLDivElement>, 'children' | 'style'>
|
|
26
|
+
> &
|
|
27
|
+
Readonly<{
|
|
24
28
|
children: string;
|
|
25
29
|
markdownCustomStyles?: MarkdownStyles;
|
|
26
30
|
markdownContainerStyles?: EmailStyle;
|
|
@@ -74,21 +78,26 @@ function CodeToken({
|
|
|
74
78
|
theme: Theme;
|
|
75
79
|
inheritedStyle?: EmailStyle;
|
|
76
80
|
}): OctaneNode {
|
|
77
|
-
if (typeof token === 'string')
|
|
78
|
-
' ',
|
|
79
|
-
' ',
|
|
80
|
-
)}</span>;
|
|
81
|
+
if (typeof token === 'string')
|
|
82
|
+
return <span style={inheritedStyle}>{token.replaceAll(' ', ' ')}</span>;
|
|
81
83
|
const style = { ...inheritedStyle, ...tokenStyle(token, theme) };
|
|
82
|
-
if (Array.isArray(token.content))
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
if (Array.isArray(token.content))
|
|
85
|
+
return (
|
|
86
|
+
<>
|
|
87
|
+
@for (const child of token.content; index childIndex; key childIndex) {
|
|
88
|
+
<CodeToken token={child} theme={theme} inheritedStyle={style} />
|
|
89
|
+
}
|
|
90
|
+
</>
|
|
91
|
+
);
|
|
92
|
+
return (
|
|
93
|
+
<span style={style}>
|
|
94
|
+
{typeof token.content === 'string' ? (
|
|
95
|
+
token.content
|
|
96
|
+
) : (
|
|
97
|
+
<CodeToken token={token.content} theme={theme} inheritedStyle={style} />
|
|
98
|
+
)}
|
|
99
|
+
</span>
|
|
100
|
+
);
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
function CodeLine({
|
|
@@ -106,9 +115,9 @@ function CodeLine({
|
|
|
106
115
|
}) @{
|
|
107
116
|
<>
|
|
108
117
|
@if (lineNumbers) {
|
|
109
|
-
<span
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
<span style={{ width: '2em', height: '1em', display: 'inline-block', fontFamily }}>
|
|
119
|
+
{lineNumber}
|
|
120
|
+
</span>
|
|
112
121
|
}
|
|
113
122
|
@for (const [tokenIndex, token] of tokens.entries(); key tokenIndex) {
|
|
114
123
|
<CodeToken token={token} theme={theme} inheritedStyle={{ fontFamily }} />
|
|
@@ -128,9 +137,8 @@ export function CodeBlock({
|
|
|
128
137
|
...props
|
|
129
138
|
}: CodeBlockProps) @{
|
|
130
139
|
const grammar = Prism.languages[language];
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
) throw new Error(`CodeBlock: There is no language defined on Prism called ${String(language)}`);
|
|
140
|
+
if (grammar === undefined)
|
|
141
|
+
throw new Error(`CodeBlock: There is no language defined on Prism called ${String(language)}`);
|
|
134
142
|
const lines = code.split(/\r\n|\r|\n/gm).map((line) => Prism.tokenize(line, grammar));
|
|
135
143
|
<pre
|
|
136
144
|
{...props}
|