@sdxc/mail 2026.9.30 → 2026.10.2
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/README.md +4 -4
- package/dist/components.d.ts +14 -14
- package/dist/components.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/markdown.d.ts +3 -3
- package/dist/markdown.js +1 -1
- package/dist/render.d.ts +1 -1
- package/dist/render.js +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @sdxc/mail
|
|
2
2
|
|
|
3
3
|
Transport-agnostic transactional email: pluggable transports, one mailer that normalizes
|
|
4
|
-
every message, and a `remix/
|
|
4
|
+
every message, and a `remix/component` layout kit that renders both body parts.
|
|
5
5
|
|
|
6
6
|
A `Mailer` owns normalization — sender defaults, address coercion, plain-text derivation,
|
|
7
7
|
validation — and hands the result to a `Transport`, the only piece that knows a provider.
|
|
@@ -15,7 +15,7 @@ npm add @sdxc/mail
|
|
|
15
15
|
|
|
16
16
|
Send outcomes are reported as a `Result` from
|
|
17
17
|
[`@sdxc/result`](https://www.npmjs.com/package/@sdxc/result), which is where `isFailure`
|
|
18
|
-
and `unwrap` come from, and bodies are `remix/
|
|
18
|
+
and `unwrap` come from, and bodies are `remix/component` trees from
|
|
19
19
|
[`remix`](https://www.npmjs.com/package/remix). The middleware records deferred sends on
|
|
20
20
|
the current log from [`@sdxc/logger`](https://www.npmjs.com/package/@sdxc/logger), and
|
|
21
21
|
`@sdxc/mail/markdown` renders documents parsed by
|
|
@@ -60,7 +60,7 @@ second authoring step.
|
|
|
60
60
|
|
|
61
61
|
```tsx
|
|
62
62
|
import type { Email as EmailContract } from "@sdxc/mail";
|
|
63
|
-
import type { Handle } from "remix/
|
|
63
|
+
import type { Handle } from "remix/component";
|
|
64
64
|
|
|
65
65
|
import { Email } from "@sdxc/mail";
|
|
66
66
|
|
|
@@ -259,7 +259,7 @@ product identity.
|
|
|
259
259
|
|
|
260
260
|
### Types
|
|
261
261
|
|
|
262
|
-
`Result` below comes from `@sdxc/result` and `RemixElement` from `remix/
|
|
262
|
+
`Result` below comes from `@sdxc/result` and `RemixElement` from `remix/component`.
|
|
263
263
|
|
|
264
264
|
```typescript
|
|
265
265
|
interface Address {
|
package/dist/components.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @author [Sergio Xalambrí](https://sergiodxa.com)
|
|
8
8
|
* @copyright Sergio Xalambrí 2026
|
|
9
9
|
*/
|
|
10
|
-
import type { Handle, RemixNode } from "remix/
|
|
10
|
+
import type { Handle, RemixNode } from "remix/component";
|
|
11
11
|
/**
|
|
12
12
|
* A web font to load, and what to use instead everywhere it does not arrive. It
|
|
13
13
|
* is a prop of {@link Layout} instead of its own component because `@font-face`
|
|
@@ -84,7 +84,7 @@ export declare namespace Layout {
|
|
|
84
84
|
*
|
|
85
85
|
* @example <Email.Layout preview="Your invite is ready"><Email.Text>Hi</Email.Text></Email.Layout>
|
|
86
86
|
*/
|
|
87
|
-
export declare function Layout(handle: Handle<Layout.Props>): () => import("remix/
|
|
87
|
+
export declare function Layout(handle: Handle<Layout.Props>): () => import("remix/component").RemixElement;
|
|
88
88
|
export declare namespace Heading {
|
|
89
89
|
/** Props accepted by {@link Heading}. */
|
|
90
90
|
interface Props {
|
|
@@ -104,7 +104,7 @@ export declare namespace Heading {
|
|
|
104
104
|
*
|
|
105
105
|
* @example <Email.Heading level={2}>You have been invited</Email.Heading>
|
|
106
106
|
*/
|
|
107
|
-
export declare function Heading(handle: Handle<Heading.Props>): () => import("remix/
|
|
107
|
+
export declare function Heading(handle: Handle<Heading.Props>): () => import("remix/component").RemixElement;
|
|
108
108
|
export declare namespace Text {
|
|
109
109
|
/** Props accepted by {@link Text}. */
|
|
110
110
|
interface Props {
|
|
@@ -126,7 +126,7 @@ export declare namespace Text {
|
|
|
126
126
|
*
|
|
127
127
|
* @example <Email.Text muted>This link expires in 24 hours.</Email.Text>
|
|
128
128
|
*/
|
|
129
|
-
export declare function Text(handle: Handle<Text.Props>): () => import("remix/
|
|
129
|
+
export declare function Text(handle: Handle<Text.Props>): () => import("remix/component").RemixElement;
|
|
130
130
|
export declare namespace Button {
|
|
131
131
|
/** Props accepted by {@link Button}. */
|
|
132
132
|
interface Props {
|
|
@@ -149,7 +149,7 @@ export declare namespace Button {
|
|
|
149
149
|
*
|
|
150
150
|
* @example <Email.Button href={url}>Accept invite</Email.Button>
|
|
151
151
|
*/
|
|
152
|
-
export declare function Button(handle: Handle<Button.Props>): () => import("remix/
|
|
152
|
+
export declare function Button(handle: Handle<Button.Props>): () => import("remix/component").RemixElement;
|
|
153
153
|
export declare namespace Table {
|
|
154
154
|
/** One row: what is being reported, and what it says. */
|
|
155
155
|
interface Row {
|
|
@@ -173,7 +173,7 @@ export declare namespace Table {
|
|
|
173
173
|
*
|
|
174
174
|
* @example <Email.Table rows={[{ label: "Status", value: "Up" }]} />
|
|
175
175
|
*/
|
|
176
|
-
export declare function Table(handle: Handle<Table.Props>): () => import("remix/
|
|
176
|
+
export declare function Table(handle: Handle<Table.Props>): () => import("remix/component").RemixElement | null;
|
|
177
177
|
export declare namespace Footer {
|
|
178
178
|
/** Props accepted by {@link Footer}. */
|
|
179
179
|
interface Props {
|
|
@@ -191,7 +191,7 @@ export declare namespace Footer {
|
|
|
191
191
|
*
|
|
192
192
|
* @example <Email.Footer>Sent because you were invited to a team.</Email.Footer>
|
|
193
193
|
*/
|
|
194
|
-
export declare function Footer(handle: Handle<Footer.Props>): () => import("remix/
|
|
194
|
+
export declare function Footer(handle: Handle<Footer.Props>): () => import("remix/component").RemixElement;
|
|
195
195
|
export declare namespace Section {
|
|
196
196
|
/** Props accepted by {@link Section}. */
|
|
197
197
|
interface Props {
|
|
@@ -212,7 +212,7 @@ export declare namespace Section {
|
|
|
212
212
|
*
|
|
213
213
|
* @example <Email.Section padding="24px 0"><Email.Text>Grouped copy</Email.Text></Email.Section>
|
|
214
214
|
*/
|
|
215
|
-
export declare function Section(handle: Handle<Section.Props>): () => import("remix/
|
|
215
|
+
export declare function Section(handle: Handle<Section.Props>): () => import("remix/component").RemixElement;
|
|
216
216
|
export declare namespace Row {
|
|
217
217
|
/** Props accepted by {@link Row}. */
|
|
218
218
|
interface Props {
|
|
@@ -229,7 +229,7 @@ export declare namespace Row {
|
|
|
229
229
|
*
|
|
230
230
|
* @example <Email.Row><Email.Column width="50%">Left</Email.Column><Email.Column>Right</Email.Column></Email.Row>
|
|
231
231
|
*/
|
|
232
|
-
export declare function Row(handle: Handle<Row.Props>): () => import("remix/
|
|
232
|
+
export declare function Row(handle: Handle<Row.Props>): () => import("remix/component").RemixElement;
|
|
233
233
|
export declare namespace Column {
|
|
234
234
|
/** Props accepted by {@link Column}. */
|
|
235
235
|
interface Props {
|
|
@@ -256,7 +256,7 @@ export declare namespace Column {
|
|
|
256
256
|
*
|
|
257
257
|
* @example <Email.Column width="120" valign="top"><Email.Img src={logo} alt="Acme" /></Email.Column>
|
|
258
258
|
*/
|
|
259
|
-
export declare function Column(handle: Handle<Column.Props>): () => import("remix/
|
|
259
|
+
export declare function Column(handle: Handle<Column.Props>): () => import("remix/component").RemixElement;
|
|
260
260
|
export declare namespace Link {
|
|
261
261
|
/** Props accepted by {@link Link}. */
|
|
262
262
|
interface Props {
|
|
@@ -277,7 +277,7 @@ export declare namespace Link {
|
|
|
277
277
|
*
|
|
278
278
|
* @example <Email.Link href={url}>the settings page</Email.Link>
|
|
279
279
|
*/
|
|
280
|
-
export declare function Link(handle: Handle<Link.Props>): () => import("remix/
|
|
280
|
+
export declare function Link(handle: Handle<Link.Props>): () => import("remix/component").RemixElement;
|
|
281
281
|
export declare namespace Img {
|
|
282
282
|
/** Props accepted by {@link Img}. */
|
|
283
283
|
interface Props {
|
|
@@ -306,7 +306,7 @@ export declare namespace Img {
|
|
|
306
306
|
*
|
|
307
307
|
* @example <Email.Img src="https://acme.com/logo.png" alt="Acme" width={120} />
|
|
308
308
|
*/
|
|
309
|
-
export declare function Img(handle: Handle<Img.Props>): () => import("remix/
|
|
309
|
+
export declare function Img(handle: Handle<Img.Props>): () => import("remix/component").RemixElement;
|
|
310
310
|
export declare namespace Hr {
|
|
311
311
|
/** Props accepted by {@link Hr}. */
|
|
312
312
|
interface Props {
|
|
@@ -323,7 +323,7 @@ export declare namespace Hr {
|
|
|
323
323
|
*
|
|
324
324
|
* @example <Email.Hr />
|
|
325
325
|
*/
|
|
326
|
-
export declare function Hr(handle: Handle<Hr.Props>): () => import("remix/
|
|
326
|
+
export declare function Hr(handle: Handle<Hr.Props>): () => import("remix/component").RemixElement;
|
|
327
327
|
/** Monospace stack, chosen so no family needs quoting inside a `style` attribute. */
|
|
328
328
|
export declare const MONO_FAMILY = "ui-monospace, SFMono-Regular, Menlo, Consolas, Liberation Mono, monospace";
|
|
329
329
|
/** Fill behind code, light enough to sit inside the card without reading as a block. */
|
|
@@ -343,4 +343,4 @@ export declare namespace CodeInline {
|
|
|
343
343
|
*
|
|
344
344
|
* @example <Email.Text>Set <Email.CodeInline>DEBUG=1</Email.CodeInline> and retry.</Email.Text>
|
|
345
345
|
*/
|
|
346
|
-
export declare function CodeInline(handle: Handle<CodeInline.Props>): () => import("remix/
|
|
346
|
+
export declare function CodeInline(handle: Handle<CodeInline.Props>): () => import("remix/component").RemixElement;
|
package/dist/components.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "remix/
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "remix/component/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* Font stack that resolves to a native UI face in every major mail client. No family
|
|
4
4
|
* needs quoting, which keeps the inline style free of escaped character references.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Transport-agnostic transactional mail: the message contract, the mailer that
|
|
3
|
-
* normalizes and delivers it, the rendering layer that turns a `remix/
|
|
3
|
+
* normalizes and delivers it, the rendering layer that turns a `remix/component` tree into
|
|
4
4
|
* both body parts, and the unbranded layout kit for authoring one. Transports live
|
|
5
5
|
* behind their own subpaths so importing one never pulls another's dependency.
|
|
6
6
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Transport-agnostic transactional mail: the message contract, the mailer that
|
|
3
|
-
* normalizes and delivers it, the rendering layer that turns a `remix/
|
|
3
|
+
* normalizes and delivers it, the rendering layer that turns a `remix/component` tree into
|
|
4
4
|
* both body parts, and the unbranded layout kit for authoring one. Transports live
|
|
5
5
|
* behind their own subpaths so importing one never pulls another's dependency.
|
|
6
6
|
*
|
package/dist/markdown.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { Token } from "@sdxc/highlight";
|
|
10
10
|
import type { Markdown as Ast } from "@sdxc/markdown";
|
|
11
|
-
import type { Handle } from "remix/
|
|
11
|
+
import type { Handle } from "remix/component";
|
|
12
12
|
export declare namespace CodeBlock {
|
|
13
13
|
/** Props accepted by {@link CodeBlock}. */
|
|
14
14
|
interface Props {
|
|
@@ -27,7 +27,7 @@ export declare namespace CodeBlock {
|
|
|
27
27
|
*
|
|
28
28
|
* @example <CodeBlock language="bash" code="bun run deploy" />
|
|
29
29
|
*/
|
|
30
|
-
export declare function CodeBlock(handle: Handle<CodeBlock.Props>): () => import("remix/
|
|
30
|
+
export declare function CodeBlock(handle: Handle<CodeBlock.Props>): () => import("remix/component").RemixElement;
|
|
31
31
|
export declare namespace Markdown {
|
|
32
32
|
/** Props accepted by {@link Markdown}. */
|
|
33
33
|
interface Props {
|
|
@@ -43,4 +43,4 @@ export declare namespace Markdown {
|
|
|
43
43
|
*
|
|
44
44
|
* @example <Markdown document={notes} />
|
|
45
45
|
*/
|
|
46
|
-
export declare function Markdown(handle: Handle<Markdown.Props>): () => import("remix/
|
|
46
|
+
export declare function Markdown(handle: Handle<Markdown.Props>): () => import("remix/component").RemixElement;
|
package/dist/markdown.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "remix/
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "remix/component/jsx-runtime";
|
|
2
2
|
import { tokenize } from "@sdxc/highlight";
|
|
3
3
|
import { CODE_COLOR, CodeInline, Heading, Hr, Img, Link, MONO_FAMILY, Text } from "./components.js";
|
|
4
4
|
/**
|
package/dist/render.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @author [Sergio Xalambrí](https://sergiodxa.com)
|
|
7
7
|
* @copyright Sergio Xalambrí 2026
|
|
8
8
|
*/
|
|
9
|
-
import type { RemixElement } from "remix/
|
|
9
|
+
import type { RemixElement } from "remix/component";
|
|
10
10
|
/** The two body parts produced from a single email tree. */
|
|
11
11
|
export interface RenderedEmail {
|
|
12
12
|
/** Serialized HTML of the tree. */
|
package/dist/render.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @author [Sergio Xalambrí](https://sergiodxa.com)
|
|
7
7
|
* @copyright Sergio Xalambrí 2026
|
|
8
8
|
*/
|
|
9
|
-
import { renderToString } from "remix/
|
|
9
|
+
import { renderToString } from "remix/component/server";
|
|
10
10
|
import { htmlToText } from "./lib/html-to-text.js";
|
|
11
11
|
/**
|
|
12
12
|
* The document type every mail client is calibrated against.
|
package/dist/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @copyright Sergio Xalambrí 2026
|
|
8
8
|
*/
|
|
9
9
|
import type { Result } from "@sdxc/result";
|
|
10
|
-
import type { RemixElement } from "remix/
|
|
10
|
+
import type { RemixElement } from "remix/component";
|
|
11
11
|
import type { MailError } from "./errors.js";
|
|
12
12
|
/** A single mailbox, optionally with the display name clients show instead of it. */
|
|
13
13
|
export interface Address {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdxc/mail",
|
|
3
|
-
"version": "2026.
|
|
4
|
-
"description": "Transport-agnostic transactional email with pluggable transports and remix/
|
|
3
|
+
"version": "2026.10.2",
|
|
4
|
+
"description": "Transport-agnostic transactional email with pluggable transports and remix/component rendering",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
"./unsubscribe": "./dist/unsubscribe.js"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@sdxc/crypto": "2026.
|
|
17
|
-
"@sdxc/highlight": "2026.
|
|
18
|
-
"@sdxc/logger": "2026.
|
|
19
|
-
"@sdxc/markdown": "2026.
|
|
20
|
-
"@sdxc/result": "2026.
|
|
21
|
-
"remix": "3.0.0
|
|
16
|
+
"@sdxc/crypto": "2026.10.2",
|
|
17
|
+
"@sdxc/highlight": "2026.10.2",
|
|
18
|
+
"@sdxc/logger": "2026.10.2",
|
|
19
|
+
"@sdxc/markdown": "2026.10.2",
|
|
20
|
+
"@sdxc/result": "2026.10.2",
|
|
21
|
+
"remix": "3.0.0"
|
|
22
22
|
},
|
|
23
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "7582e46f150b052ba145945661ac9937f5f26f27",
|
|
24
24
|
"publishConfig": {
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|