@resq-systems/email-templates 0.6.0 → 0.6.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.
Files changed (91) hide show
  1. package/lib/contract.d.ts +56 -43
  2. package/lib/contract.d.ts.map +1 -1
  3. package/lib/contract.js +12 -1
  4. package/lib/contract.js.map +1 -1
  5. package/lib/emails/incident-alert.d.ts +1 -0
  6. package/lib/emails/incident-alert.d.ts.map +1 -1
  7. package/lib/emails/incident-alert.js.map +1 -1
  8. package/lib/emails/index.d.ts +1 -1
  9. package/lib/emails/mission-approval.d.ts +1 -0
  10. package/lib/emails/mission-approval.d.ts.map +1 -1
  11. package/lib/emails/mission-approval.js.map +1 -1
  12. package/lib/emails/new-device-login.d.ts +1 -0
  13. package/lib/emails/new-device-login.d.ts.map +1 -1
  14. package/lib/emails/new-device-login.js.map +1 -1
  15. package/lib/emails/notification.d.ts +1 -0
  16. package/lib/emails/notification.d.ts.map +1 -1
  17. package/lib/emails/notification.js.map +1 -1
  18. package/lib/emails/org-invitation.d.ts +1 -0
  19. package/lib/emails/org-invitation.d.ts.map +1 -1
  20. package/lib/emails/org-invitation.js.map +1 -1
  21. package/lib/emails/otp.d.ts +1 -0
  22. package/lib/emails/otp.d.ts.map +1 -1
  23. package/lib/emails/otp.js.map +1 -1
  24. package/lib/emails/password-changed.d.ts +1 -0
  25. package/lib/emails/password-changed.d.ts.map +1 -1
  26. package/lib/emails/password-changed.js.map +1 -1
  27. package/lib/emails/password-reset.d.ts +1 -0
  28. package/lib/emails/password-reset.d.ts.map +1 -1
  29. package/lib/emails/password-reset.js.map +1 -1
  30. package/lib/emails/primitives.d.ts.map +1 -1
  31. package/lib/emails/primitives.js +7 -0
  32. package/lib/emails/primitives.js.map +1 -1
  33. package/lib/emails/theme.d.ts +86 -8
  34. package/lib/emails/theme.d.ts.map +1 -1
  35. package/lib/emails/theme.js +51 -3
  36. package/lib/emails/theme.js.map +1 -1
  37. package/lib/emails/tokens.d.ts +2 -1
  38. package/lib/emails/tokens.d.ts.map +1 -1
  39. package/lib/emails/tokens.js +7 -0
  40. package/lib/emails/tokens.js.map +1 -1
  41. package/lib/emails/welcome.d.ts +1 -0
  42. package/lib/emails/welcome.d.ts.map +1 -1
  43. package/lib/emails/welcome.js.map +1 -1
  44. package/lib/index.d.ts +1 -1
  45. package/lib/mailer.d.ts +118 -11
  46. package/lib/mailer.d.ts.map +1 -1
  47. package/lib/mailer.js +48 -2
  48. package/lib/mailer.js.map +1 -1
  49. package/lib/node_modules/@react-email/tailwind/dist/index.d.ts +1 -1
  50. package/lib/node_modules/{tailwindcss → @react-email/tailwind/node_modules/tailwindcss}/dist/colors.d.ts +1 -1
  51. package/lib/node_modules/@react-email/tailwind/node_modules/tailwindcss/dist/colors.d.ts.map +1 -0
  52. package/lib/node_modules/{tailwindcss → @react-email/tailwind/node_modules/tailwindcss}/dist/lib.d.ts +1 -1
  53. package/lib/node_modules/@react-email/tailwind/node_modules/tailwindcss/dist/lib.d.ts.map +1 -0
  54. package/lib/node_modules/{tailwindcss → @react-email/tailwind/node_modules/tailwindcss}/dist/resolve-config-QUZ9b-Gn.d.ts +1 -1
  55. package/lib/node_modules/@react-email/tailwind/node_modules/tailwindcss/dist/resolve-config-QUZ9b-Gn.d.ts.map +1 -0
  56. package/lib/node_modules/{tailwindcss → @react-email/tailwind/node_modules/tailwindcss}/dist/types-DWdTiksJ.d.ts +1 -1
  57. package/lib/node_modules/@react-email/tailwind/node_modules/tailwindcss/dist/types-DWdTiksJ.d.ts.map +1 -0
  58. package/lib/registry.d.ts.map +1 -1
  59. package/lib/registry.js +6 -0
  60. package/lib/registry.js.map +1 -1
  61. package/lib/render.d.ts +9 -2
  62. package/lib/render.d.ts.map +1 -1
  63. package/lib/render.js +16 -2
  64. package/lib/render.js.map +1 -1
  65. package/lib/schemas.d.ts +9 -0
  66. package/lib/schemas.d.ts.map +1 -1
  67. package/lib/schemas.js +16 -0
  68. package/lib/schemas.js.map +1 -1
  69. package/lib/send/index.d.ts +1 -1
  70. package/lib/send/resend-sender.d.ts +11 -0
  71. package/lib/send/resend-sender.d.ts.map +1 -1
  72. package/lib/send/resend-sender.js +17 -0
  73. package/lib/send/resend-sender.js.map +1 -1
  74. package/lib/send/send-email.d.ts +21 -0
  75. package/lib/send/send-email.d.ts.map +1 -1
  76. package/lib/send/send-email.js +26 -0
  77. package/lib/send/send-email.js.map +1 -1
  78. package/lib/send/sender.d.ts +26 -2
  79. package/lib/send/sender.d.ts.map +1 -1
  80. package/lib/suite.d.ts.map +1 -1
  81. package/lib/suite.js +7 -0
  82. package/lib/suite.js.map +1 -1
  83. package/lib/templates.d.ts +9 -0
  84. package/lib/templates.d.ts.map +1 -1
  85. package/lib/templates.js +16 -0
  86. package/lib/templates.js.map +1 -1
  87. package/package.json +7 -7
  88. package/lib/node_modules/tailwindcss/dist/colors.d.ts.map +0 -1
  89. package/lib/node_modules/tailwindcss/dist/lib.d.ts.map +0 -1
  90. package/lib/node_modules/tailwindcss/dist/resolve-config-QUZ9b-Gn.d.ts.map +0 -1
  91. package/lib/node_modules/tailwindcss/dist/types-DWdTiksJ.d.ts.map +0 -1
@@ -2,21 +2,45 @@ import { EmailCategory } from "../schemas.js";
2
2
  import { TailwindConfig } from "../node_modules/@react-email/tailwind/dist/index.js";
3
3
  import { ReactElement } from "react";
4
4
  //#region src/emails/theme.d.ts
5
+ /**
6
+ * Font stacks the theme exposes to Tailwind's `fontFamily` extension. Each array
7
+ * is a CSS font-family stack in priority order (preferred face first, generic
8
+ * fallback last); multi-word names are pre-quoted so they drop straight into a
9
+ * `font-family` value.
10
+ */
5
11
  interface EmailThemeFonts {
12
+ /** Stack for display/heading text. */
6
13
  display: string[];
14
+ /** Stack for body/sans text. */
7
15
  sans: string[];
16
+ /** Stack for monospace text (codes, metadata). */
8
17
  mono: string[];
9
18
  }
10
- /** Organization identity rendered into email chrome (header, signature, footer). */
19
+ /**
20
+ * Organization identity rendered into email chrome (header, signature, footer).
21
+ *
22
+ * All `*Url` fields are absolute URLs. {@link EmailOrgIdentity.registeredAddress}
23
+ * leads with the legal entity name, so it stands alone as a complete CAN-SPAM
24
+ * postal line without a separate `legalName` line in the footer.
25
+ */
11
26
  interface EmailOrgIdentity {
27
+ /** Short brand name used in sign-offs, e.g. "— The {brandName} team". */
12
28
  brandName: string;
29
+ /** Product name shown in the header lockup beside the logo. */
13
30
  productName: string;
31
+ /** Full legal entity name. */
14
32
  legalName: string;
33
+ /** Registered postal address, prefixed with the legal name; a complete CAN-SPAM line. */
15
34
  registeredAddress: string;
35
+ /** Support inbox address, rendered as a `mailto:` link. */
16
36
  supportEmail: string;
37
+ /** Marketing/website URL (absolute). Never used as an unsubscribe target. */
17
38
  websiteUrl: string;
39
+ /** Absolute URL of the Terms page. */
18
40
  termsUrl: string;
41
+ /** Absolute URL of the Privacy page. */
19
42
  privacyUrl: string;
43
+ /** Absolute URL of the header logo image. */
20
44
  logoUrl: string;
21
45
  }
22
46
  /** The full, resolved theme every template renders against. */
@@ -30,22 +54,58 @@ interface EmailTheme {
30
54
  /** Optional stylesheet `<link>` injected in `<Head>` for brand webfonts. */
31
55
  fontsHref?: string;
32
56
  }
33
- /** A partial theme a consumer supplies to rebrand; unset keys fall back to the base. */
57
+ /**
58
+ * A partial theme a consumer supplies to rebrand; unset keys fall back to the
59
+ * base. All object fields are **shallow**-merged over the base one level deep (see
60
+ * {@link resolveEmailTheme}), so supplying `colors` replaces only the named color
61
+ * tokens, not the whole palette.
62
+ */
34
63
  interface EmailThemeOverride {
64
+ /** Color tokens to override (email-safe hex); merged over the base palette. */
35
65
  colors?: Record<string, string>;
66
+ /** Font stacks to override; unspecified stacks keep the base. */
36
67
  fonts?: Partial<EmailThemeFonts>;
37
68
  /** Override organization identity fields (shallow-merged over the base). */
38
69
  org?: Partial<EmailOrgIdentity>;
39
- /** Pass `null` to drop the webfont link entirely. */
70
+ /** Replace the webfont `<link>` href, or pass `null` to drop it entirely. */
40
71
  fontsHref?: string | null;
41
72
  }
42
73
  /** The default ResQ Systems brand theme (dark-first, red primary, Syne/DM Sans/DM Mono). */
43
74
  declare const defaultEmailTheme: EmailTheme;
44
- /** Merge an override onto a base theme (colors/fonts shallow-merge; `fontsHref: null` removes it). */
75
+ /**
76
+ * Merge an override onto a base theme, producing a new resolved theme.
77
+ *
78
+ * Pure — never mutates `base`. `colors`, `fonts`, and `org` are **shallow**-merged
79
+ * (override keys replace base keys one level deep), so a partial `fonts` override
80
+ * keeps the base's other stacks. `fontsHref` follows a three-way rule: `null`
81
+ * drops the webfont link entirely, absent/`undefined` keeps the base href, and any
82
+ * string replaces it.
83
+ *
84
+ * @param base - The theme to start from.
85
+ * @param override - Fields to overlay; when omitted, `base` is returned by reference.
86
+ * @returns The merged theme, or `base` itself when there is no override.
87
+ */
45
88
  declare function resolveEmailTheme(base: EmailTheme, override?: EmailThemeOverride): EmailTheme;
46
- /** Merge an override onto the default ResQ Systems theme. */
89
+ /**
90
+ * Merge an override onto the default ResQ Systems theme.
91
+ *
92
+ * Pure convenience wrapper over {@link resolveEmailTheme} with
93
+ * {@link defaultEmailTheme} as the base.
94
+ *
95
+ * @param override - Fields to overlay on the default theme.
96
+ * @returns The resolved theme.
97
+ */
47
98
  declare function mergeEmailTheme(override?: EmailThemeOverride): EmailTheme;
48
- /** Build the `<Tailwind config>` object from a resolved theme. */
99
+ /**
100
+ * Build the `<Tailwind config>` object from a resolved theme.
101
+ *
102
+ * Pure — projects the theme's colors and font stacks into a Tailwind
103
+ * `theme.extend` config atop the pixel-based preset (email clients need px units,
104
+ * not rem).
105
+ *
106
+ * @param theme - The resolved theme to project.
107
+ * @returns The config object to pass to react-email's `<Tailwind>`.
108
+ */
49
109
  declare function buildTailwindConfig(theme: EmailTheme): {
50
110
  presets: TailwindConfig[];
51
111
  theme: {
@@ -67,13 +127,25 @@ declare const EmailThemeContext: import("react").Context<EmailTheme>;
67
127
  * Wrap an element so it renders against a theme override (used by `renderEmail`).
68
128
  * Returns the element unchanged when there is no override, so the default theme
69
129
  * flows through context.
130
+ *
131
+ * Pure — builds a new provider element and does not mutate `element`.
132
+ *
133
+ * @param element - The email element tree to wrap.
134
+ * @param override - Theme fields to overlay; when omitted, `element` is returned unchanged.
135
+ * @returns `element`, wrapped in an {@link EmailThemeContext} provider when an override is given.
70
136
  */
71
137
  declare function withEmailTheme(element: ReactElement, override?: EmailThemeOverride): ReactElement;
72
- /** Per-send message policy carried through context to the legal footer. */
138
+ /**
139
+ * Per-send message policy carried through context to the legal footer.
140
+ *
141
+ * The unsubscribe affordance renders only when {@link EmailMessage.category} is
142
+ * `"marketing"` **and** {@link EmailMessage.unsubscribeUrl} is set; a marketing
143
+ * send with no `unsubscribeUrl` simply omits it (there is no homepage fallback).
144
+ */
73
145
  interface EmailMessage {
74
146
  /** Compliance class; defaults to `transactional`. */
75
147
  category: EmailCategory;
76
- /** Where the unsubscribe/preferences link points (used for `marketing`). */
148
+ /** Absolute unsubscribe/preferences URL; only consulted for `marketing` sends. */
77
149
  unsubscribeUrl?: string;
78
150
  }
79
151
  /** Context carrying the active message policy; defaults to a transactional send. */
@@ -82,6 +154,12 @@ declare const EmailMessageContext: import("react").Context<EmailMessage>;
82
154
  * Wrap an element so it renders against a message policy (used by `renderEmail`).
83
155
  * Returns the element unchanged when no message is given, so the default
84
156
  * transactional policy flows through context.
157
+ *
158
+ * Pure — builds a new provider element and does not mutate `element`.
159
+ *
160
+ * @param element - The email element tree to wrap.
161
+ * @param message - The per-send policy; when omitted, `element` is returned unchanged.
162
+ * @returns `element`, wrapped in an {@link EmailMessageContext} provider when a message is given.
85
163
  */
86
164
  declare function withEmailMessage(element: ReactElement, message?: EmailMessage): ReactElement;
87
165
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","names":[],"sources":["../../src/emails/theme.tsx"],"mappings":";;;;UAqBiB;EAChB;EACA;EACA;;;UAIgB;EAChB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;UAIgB;;EAEhB,QAAQ;;EAER,OAAO;;EAEP,KAAK;;EAEL;;;UAIgB;EAChB,SAAS;EACT,QAAQ,QAAQ;;EAEhB,MAAM,QAAQ;;EAEd;;;cAIY,mBAAmB;;iBAYhB,kBAAkB,MAAM,YAAY,WAAW,qBAAqB;;iBAWpE,gBAAgB,WAAW,qBAAqB;;iBAKhD,oBAAoB,OAAO;WAAA;;;;;;;QAOtC;QACA;QACA;;;;;;cAQQ,mCAAiB,QAAA;;;;;;iBAOd,eAAe,SAAS,cAAc,WAAW,qBAAqB;;UAMrE;;EAEhB,UAAU;;EAEV;;;cAIY,qCAAmB,QAAA;;;;;;iBAOhB,iBAAiB,SAAS,cAAc,UAAU,eAAe"}
1
+ {"version":3,"file":"theme.d.ts","names":[],"sources":["../../src/emails/theme.tsx"],"mappings":";;;;;;;;;;UAqCiB;;EAEhB;;EAEA;;EAEA;;;;;;;;;UAUgB;;EAEhB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;UAIgB;;EAEhB,QAAQ;;EAER,OAAO;;EAEP,KAAK;;EAEL;;;;;;;;UASgB;;EAEhB,SAAS;;EAET,QAAQ,QAAQ;;EAEhB,MAAM,QAAQ;;EAEd;;;cAQY,mBAAmB;;;;;;;;;;;;;;iBAwBhB,kBAAkB,MAAM,YAAY,WAAW,qBAAqB;;;;;;;;;;iBAmBpE,gBAAgB,WAAW,qBAAqB;;;;;;;;;;;iBAchD,oBAAoB,OAAO;WAAA;;;;;;;QAOtC;QACA;QACA;;;;;;cAQQ,mCAAiB,QAAA;;;;;;;;;;;;iBAad,eAAe,SAAS,cAAc,WAAW,qBAAqB;;;;;;;;UAYrE;;EAEhB,UAAU;;EAEV;;;cAIY,qCAAmB,QAAA;;;;;;;;;;;;iBAahB,iBAAiB,SAAS,cAAc,UAAU,eAAe"}
@@ -17,6 +17,13 @@ import { createContext, createElement } from "react";
17
17
  * See the License for the specific language governing permissions and
18
18
  * limitations under the License.
19
19
  */
20
+ /**
21
+ * @fileoverview Email theming system — the resolved `EmailTheme` shape, override
22
+ * merging, the Tailwind config builder, and React contexts carrying the active theme
23
+ * and per-send message policy.
24
+ *
25
+ * @module @resq-systems/email-templates/emails/theme
26
+ */
20
27
  /** The default ResQ Systems brand theme (dark-first, red primary, Syne/DM Sans/DM Mono). */
21
28
  const defaultEmailTheme = {
22
29
  colors: { ...emailColors },
@@ -28,7 +35,19 @@ const defaultEmailTheme = {
28
35
  org: { ...emailOrg },
29
36
  fontsHref: emailFonts.googleFontsHref
30
37
  };
31
- /** Merge an override onto a base theme (colors/fonts shallow-merge; `fontsHref: null` removes it). */
38
+ /**
39
+ * Merge an override onto a base theme, producing a new resolved theme.
40
+ *
41
+ * Pure — never mutates `base`. `colors`, `fonts`, and `org` are **shallow**-merged
42
+ * (override keys replace base keys one level deep), so a partial `fonts` override
43
+ * keeps the base's other stacks. `fontsHref` follows a three-way rule: `null`
44
+ * drops the webfont link entirely, absent/`undefined` keeps the base href, and any
45
+ * string replaces it.
46
+ *
47
+ * @param base - The theme to start from.
48
+ * @param override - Fields to overlay; when omitted, `base` is returned by reference.
49
+ * @returns The merged theme, or `base` itself when there is no override.
50
+ */
32
51
  function resolveEmailTheme(base, override) {
33
52
  if (!override) return base;
34
53
  return {
@@ -47,11 +66,28 @@ function resolveEmailTheme(base, override) {
47
66
  fontsHref: override.fontsHref === null ? void 0 : override.fontsHref ?? base.fontsHref
48
67
  };
49
68
  }
50
- /** Merge an override onto the default ResQ Systems theme. */
69
+ /**
70
+ * Merge an override onto the default ResQ Systems theme.
71
+ *
72
+ * Pure convenience wrapper over {@link resolveEmailTheme} with
73
+ * {@link defaultEmailTheme} as the base.
74
+ *
75
+ * @param override - Fields to overlay on the default theme.
76
+ * @returns The resolved theme.
77
+ */
51
78
  function mergeEmailTheme(override) {
52
79
  return resolveEmailTheme(defaultEmailTheme, override);
53
80
  }
54
- /** Build the `<Tailwind config>` object from a resolved theme. */
81
+ /**
82
+ * Build the `<Tailwind config>` object from a resolved theme.
83
+ *
84
+ * Pure — projects the theme's colors and font stacks into a Tailwind
85
+ * `theme.extend` config atop the pixel-based preset (email clients need px units,
86
+ * not rem).
87
+ *
88
+ * @param theme - The resolved theme to project.
89
+ * @returns The config object to pass to react-email's `<Tailwind>`.
90
+ */
55
91
  function buildTailwindConfig(theme) {
56
92
  return {
57
93
  presets: [pixelBasedPreset],
@@ -71,6 +107,12 @@ const EmailThemeContext = createContext(defaultEmailTheme);
71
107
  * Wrap an element so it renders against a theme override (used by `renderEmail`).
72
108
  * Returns the element unchanged when there is no override, so the default theme
73
109
  * flows through context.
110
+ *
111
+ * Pure — builds a new provider element and does not mutate `element`.
112
+ *
113
+ * @param element - The email element tree to wrap.
114
+ * @param override - Theme fields to overlay; when omitted, `element` is returned unchanged.
115
+ * @returns `element`, wrapped in an {@link EmailThemeContext} provider when an override is given.
74
116
  */
75
117
  function withEmailTheme(element, override) {
76
118
  if (!override) return element;
@@ -82,6 +124,12 @@ const EmailMessageContext = createContext({ category: "transactional" });
82
124
  * Wrap an element so it renders against a message policy (used by `renderEmail`).
83
125
  * Returns the element unchanged when no message is given, so the default
84
126
  * transactional policy flows through context.
127
+ *
128
+ * Pure — builds a new provider element and does not mutate `element`.
129
+ *
130
+ * @param element - The email element tree to wrap.
131
+ * @param message - The per-send policy; when omitted, `element` is returned unchanged.
132
+ * @returns `element`, wrapped in an {@link EmailMessageContext} provider when a message is given.
85
133
  */
86
134
  function withEmailMessage(element, message) {
87
135
  if (!message) return element;
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","names":[],"sources":["../../src/emails/theme.tsx"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { pixelBasedPreset } from \"@react-email/components\";\nimport { type ReactElement, createContext, createElement } from \"react\";\nimport type { EmailCategory } from \"../schemas.js\";\nimport { emailColors, emailFonts, emailOrg } from \"./tokens.js\";\n\nexport interface EmailThemeFonts {\n\tdisplay: string[];\n\tsans: string[];\n\tmono: string[];\n}\n\n/** Organization identity rendered into email chrome (header, signature, footer). */\nexport interface EmailOrgIdentity {\n\tbrandName: string;\n\tproductName: string;\n\tlegalName: string;\n\tregisteredAddress: string;\n\tsupportEmail: string;\n\twebsiteUrl: string;\n\ttermsUrl: string;\n\tprivacyUrl: string;\n\tlogoUrl: string;\n}\n\n/** The full, resolved theme every template renders against. */\nexport interface EmailTheme {\n\t/** Color tokens → Tailwind `theme.extend.colors` (email-safe hex). */\n\tcolors: Record<string, string>;\n\t/** Font stacks → Tailwind `theme.extend.fontFamily` (pre-quoted multi-word names). */\n\tfonts: EmailThemeFonts;\n\t/** Organization identity for header lockup, signatures, and legal footer. */\n\torg: EmailOrgIdentity;\n\t/** Optional stylesheet `<link>` injected in `<Head>` for brand webfonts. */\n\tfontsHref?: string;\n}\n\n/** A partial theme a consumer supplies to rebrand; unset keys fall back to the base. */\nexport interface EmailThemeOverride {\n\tcolors?: Record<string, string>;\n\tfonts?: Partial<EmailThemeFonts>;\n\t/** Override organization identity fields (shallow-merged over the base). */\n\torg?: Partial<EmailOrgIdentity>;\n\t/** Pass `null` to drop the webfont link entirely. */\n\tfontsHref?: string | null;\n}\n\n/** The default ResQ Systems brand theme (dark-first, red primary, Syne/DM Sans/DM Mono). */\nexport const defaultEmailTheme: EmailTheme = {\n\tcolors: { ...emailColors },\n\tfonts: {\n\t\tdisplay: [...emailFonts.stacks.display],\n\t\tsans: [...emailFonts.stacks.body],\n\t\tmono: [...emailFonts.stacks.mono],\n\t},\n\torg: { ...emailOrg },\n\tfontsHref: emailFonts.googleFontsHref,\n};\n\n/** Merge an override onto a base theme (colors/fonts shallow-merge; `fontsHref: null` removes it). */\nexport function resolveEmailTheme(base: EmailTheme, override?: EmailThemeOverride): EmailTheme {\n\tif (!override) return base;\n\treturn {\n\t\tcolors: { ...base.colors, ...override.colors },\n\t\tfonts: { ...base.fonts, ...override.fonts },\n\t\torg: { ...base.org, ...override.org },\n\t\tfontsHref: override.fontsHref === null ? undefined : (override.fontsHref ?? base.fontsHref),\n\t};\n}\n\n/** Merge an override onto the default ResQ Systems theme. */\nexport function mergeEmailTheme(override?: EmailThemeOverride): EmailTheme {\n\treturn resolveEmailTheme(defaultEmailTheme, override);\n}\n\n/** Build the `<Tailwind config>` object from a resolved theme. */\nexport function buildTailwindConfig(theme: EmailTheme) {\n\treturn {\n\t\tpresets: [pixelBasedPreset],\n\t\ttheme: {\n\t\t\textend: {\n\t\t\t\tcolors: { ...theme.colors },\n\t\t\t\tfontFamily: {\n\t\t\t\t\tdisplay: [...theme.fonts.display],\n\t\t\t\t\tsans: [...theme.fonts.sans],\n\t\t\t\t\tmono: [...theme.fonts.mono],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n}\n\n/** Context carrying the active theme; defaults to the ResQ Systems brand. */\nexport const EmailThemeContext = createContext<EmailTheme>(defaultEmailTheme);\n\n/**\n * Wrap an element so it renders against a theme override (used by `renderEmail`).\n * Returns the element unchanged when there is no override, so the default theme\n * flows through context.\n */\nexport function withEmailTheme(element: ReactElement, override?: EmailThemeOverride): ReactElement {\n\tif (!override) return element;\n\treturn createElement(EmailThemeContext.Provider, { value: mergeEmailTheme(override) }, element);\n}\n\n/** Per-send message policy carried through context to the legal footer. */\nexport interface EmailMessage {\n\t/** Compliance class; defaults to `transactional`. */\n\tcategory: EmailCategory;\n\t/** Where the unsubscribe/preferences link points (used for `marketing`). */\n\tunsubscribeUrl?: string;\n}\n\n/** Context carrying the active message policy; defaults to a transactional send. */\nexport const EmailMessageContext = createContext<EmailMessage>({ category: \"transactional\" });\n\n/**\n * Wrap an element so it renders against a message policy (used by `renderEmail`).\n * Returns the element unchanged when no message is given, so the default\n * transactional policy flows through context.\n */\nexport function withEmailMessage(element: ReactElement, message?: EmailMessage): ReactElement {\n\tif (!message) return element;\n\treturn createElement(EmailMessageContext.Provider, { value: message }, element);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+DA,MAAa,oBAAgC;CAC5C,QAAQ,EAAE,GAAG,YAAY;CACzB,OAAO;EACN,SAAS,CAAC,GAAG,WAAW,OAAO,OAAO;EACtC,MAAM,CAAC,GAAG,WAAW,OAAO,IAAI;EAChC,MAAM,CAAC,GAAG,WAAW,OAAO,IAAI;CACjC;CACA,KAAK,EAAE,GAAG,SAAS;CACnB,WAAW,WAAW;AACvB;;AAGA,SAAgB,kBAAkB,MAAkB,UAA2C;CAC9F,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO;EACN,QAAQ;GAAE,GAAG,KAAK;GAAQ,GAAG,SAAS;EAAO;EAC7C,OAAO;GAAE,GAAG,KAAK;GAAO,GAAG,SAAS;EAAM;EAC1C,KAAK;GAAE,GAAG,KAAK;GAAK,GAAG,SAAS;EAAI;EACpC,WAAW,SAAS,cAAc,OAAO,KAAA,IAAa,SAAS,aAAa,KAAK;CAClF;AACD;;AAGA,SAAgB,gBAAgB,UAA2C;CAC1E,OAAO,kBAAkB,mBAAmB,QAAQ;AACrD;;AAGA,SAAgB,oBAAoB,OAAmB;CACtD,OAAO;EACN,SAAS,CAAC,gBAAgB;EAC1B,OAAO,EACN,QAAQ;GACP,QAAQ,EAAE,GAAG,MAAM,OAAO;GAC1B,YAAY;IACX,SAAS,CAAC,GAAG,MAAM,MAAM,OAAO;IAChC,MAAM,CAAC,GAAG,MAAM,MAAM,IAAI;IAC1B,MAAM,CAAC,GAAG,MAAM,MAAM,IAAI;GAC3B;EACD,EACD;CACD;AACD;;AAGA,MAAa,oBAAoB,cAA0B,iBAAiB;;;;;;AAO5E,SAAgB,eAAe,SAAuB,UAA6C;CAClG,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,cAAc,kBAAkB,UAAU,EAAE,OAAO,gBAAgB,QAAQ,EAAE,GAAG,OAAO;AAC/F;;AAWA,MAAa,sBAAsB,cAA4B,EAAE,UAAU,gBAAgB,CAAC;;;;;;AAO5F,SAAgB,iBAAiB,SAAuB,SAAsC;CAC7F,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO,cAAc,oBAAoB,UAAU,EAAE,OAAO,QAAQ,GAAG,OAAO;AAC/E"}
1
+ {"version":3,"file":"theme.js","names":[],"sources":["../../src/emails/theme.tsx"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Email theming system — the resolved `EmailTheme` shape, override\n * merging, the Tailwind config builder, and React contexts carrying the active theme\n * and per-send message policy.\n *\n * @module @resq-systems/email-templates/emails/theme\n */\n\nimport { pixelBasedPreset } from \"@react-email/components\";\nimport { type ReactElement, createContext, createElement } from \"react\";\nimport type { EmailCategory } from \"../schemas.js\";\nimport { emailColors, emailFonts, emailOrg } from \"./tokens.js\";\n\n//#region Types\n\n/**\n * Font stacks the theme exposes to Tailwind's `fontFamily` extension. Each array\n * is a CSS font-family stack in priority order (preferred face first, generic\n * fallback last); multi-word names are pre-quoted so they drop straight into a\n * `font-family` value.\n */\nexport interface EmailThemeFonts {\n\t/** Stack for display/heading text. */\n\tdisplay: string[];\n\t/** Stack for body/sans text. */\n\tsans: string[];\n\t/** Stack for monospace text (codes, metadata). */\n\tmono: string[];\n}\n\n/**\n * Organization identity rendered into email chrome (header, signature, footer).\n *\n * All `*Url` fields are absolute URLs. {@link EmailOrgIdentity.registeredAddress}\n * leads with the legal entity name, so it stands alone as a complete CAN-SPAM\n * postal line without a separate `legalName` line in the footer.\n */\nexport interface EmailOrgIdentity {\n\t/** Short brand name used in sign-offs, e.g. \"— The {brandName} team\". */\n\tbrandName: string;\n\t/** Product name shown in the header lockup beside the logo. */\n\tproductName: string;\n\t/** Full legal entity name. */\n\tlegalName: string;\n\t/** Registered postal address, prefixed with the legal name; a complete CAN-SPAM line. */\n\tregisteredAddress: string;\n\t/** Support inbox address, rendered as a `mailto:` link. */\n\tsupportEmail: string;\n\t/** Marketing/website URL (absolute). Never used as an unsubscribe target. */\n\twebsiteUrl: string;\n\t/** Absolute URL of the Terms page. */\n\ttermsUrl: string;\n\t/** Absolute URL of the Privacy page. */\n\tprivacyUrl: string;\n\t/** Absolute URL of the header logo image. */\n\tlogoUrl: string;\n}\n\n/** The full, resolved theme every template renders against. */\nexport interface EmailTheme {\n\t/** Color tokens → Tailwind `theme.extend.colors` (email-safe hex). */\n\tcolors: Record<string, string>;\n\t/** Font stacks → Tailwind `theme.extend.fontFamily` (pre-quoted multi-word names). */\n\tfonts: EmailThemeFonts;\n\t/** Organization identity for header lockup, signatures, and legal footer. */\n\torg: EmailOrgIdentity;\n\t/** Optional stylesheet `<link>` injected in `<Head>` for brand webfonts. */\n\tfontsHref?: string;\n}\n\n/**\n * A partial theme a consumer supplies to rebrand; unset keys fall back to the\n * base. All object fields are **shallow**-merged over the base one level deep (see\n * {@link resolveEmailTheme}), so supplying `colors` replaces only the named color\n * tokens, not the whole palette.\n */\nexport interface EmailThemeOverride {\n\t/** Color tokens to override (email-safe hex); merged over the base palette. */\n\tcolors?: Record<string, string>;\n\t/** Font stacks to override; unspecified stacks keep the base. */\n\tfonts?: Partial<EmailThemeFonts>;\n\t/** Override organization identity fields (shallow-merged over the base). */\n\torg?: Partial<EmailOrgIdentity>;\n\t/** Replace the webfont `<link>` href, or pass `null` to drop it entirely. */\n\tfontsHref?: string | null;\n}\n\n//#endregion\n\n//#region Public API\n\n/** The default ResQ Systems brand theme (dark-first, red primary, Syne/DM Sans/DM Mono). */\nexport const defaultEmailTheme: EmailTheme = {\n\tcolors: { ...emailColors },\n\tfonts: {\n\t\tdisplay: [...emailFonts.stacks.display],\n\t\tsans: [...emailFonts.stacks.body],\n\t\tmono: [...emailFonts.stacks.mono],\n\t},\n\torg: { ...emailOrg },\n\tfontsHref: emailFonts.googleFontsHref,\n};\n\n/**\n * Merge an override onto a base theme, producing a new resolved theme.\n *\n * Pure — never mutates `base`. `colors`, `fonts`, and `org` are **shallow**-merged\n * (override keys replace base keys one level deep), so a partial `fonts` override\n * keeps the base's other stacks. `fontsHref` follows a three-way rule: `null`\n * drops the webfont link entirely, absent/`undefined` keeps the base href, and any\n * string replaces it.\n *\n * @param base - The theme to start from.\n * @param override - Fields to overlay; when omitted, `base` is returned by reference.\n * @returns The merged theme, or `base` itself when there is no override.\n */\nexport function resolveEmailTheme(base: EmailTheme, override?: EmailThemeOverride): EmailTheme {\n\tif (!override) return base;\n\treturn {\n\t\tcolors: { ...base.colors, ...override.colors },\n\t\tfonts: { ...base.fonts, ...override.fonts },\n\t\torg: { ...base.org, ...override.org },\n\t\tfontsHref: override.fontsHref === null ? undefined : (override.fontsHref ?? base.fontsHref),\n\t};\n}\n\n/**\n * Merge an override onto the default ResQ Systems theme.\n *\n * Pure convenience wrapper over {@link resolveEmailTheme} with\n * {@link defaultEmailTheme} as the base.\n *\n * @param override - Fields to overlay on the default theme.\n * @returns The resolved theme.\n */\nexport function mergeEmailTheme(override?: EmailThemeOverride): EmailTheme {\n\treturn resolveEmailTheme(defaultEmailTheme, override);\n}\n\n/**\n * Build the `<Tailwind config>` object from a resolved theme.\n *\n * Pure — projects the theme's colors and font stacks into a Tailwind\n * `theme.extend` config atop the pixel-based preset (email clients need px units,\n * not rem).\n *\n * @param theme - The resolved theme to project.\n * @returns The config object to pass to react-email's `<Tailwind>`.\n */\nexport function buildTailwindConfig(theme: EmailTheme) {\n\treturn {\n\t\tpresets: [pixelBasedPreset],\n\t\ttheme: {\n\t\t\textend: {\n\t\t\t\tcolors: { ...theme.colors },\n\t\t\t\tfontFamily: {\n\t\t\t\t\tdisplay: [...theme.fonts.display],\n\t\t\t\t\tsans: [...theme.fonts.sans],\n\t\t\t\t\tmono: [...theme.fonts.mono],\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n}\n\n/** Context carrying the active theme; defaults to the ResQ Systems brand. */\nexport const EmailThemeContext = createContext<EmailTheme>(defaultEmailTheme);\n\n/**\n * Wrap an element so it renders against a theme override (used by `renderEmail`).\n * Returns the element unchanged when there is no override, so the default theme\n * flows through context.\n *\n * Pure — builds a new provider element and does not mutate `element`.\n *\n * @param element - The email element tree to wrap.\n * @param override - Theme fields to overlay; when omitted, `element` is returned unchanged.\n * @returns `element`, wrapped in an {@link EmailThemeContext} provider when an override is given.\n */\nexport function withEmailTheme(element: ReactElement, override?: EmailThemeOverride): ReactElement {\n\tif (!override) return element;\n\treturn createElement(EmailThemeContext.Provider, { value: mergeEmailTheme(override) }, element);\n}\n\n/**\n * Per-send message policy carried through context to the legal footer.\n *\n * The unsubscribe affordance renders only when {@link EmailMessage.category} is\n * `\"marketing\"` **and** {@link EmailMessage.unsubscribeUrl} is set; a marketing\n * send with no `unsubscribeUrl` simply omits it (there is no homepage fallback).\n */\nexport interface EmailMessage {\n\t/** Compliance class; defaults to `transactional`. */\n\tcategory: EmailCategory;\n\t/** Absolute unsubscribe/preferences URL; only consulted for `marketing` sends. */\n\tunsubscribeUrl?: string;\n}\n\n/** Context carrying the active message policy; defaults to a transactional send. */\nexport const EmailMessageContext = createContext<EmailMessage>({ category: \"transactional\" });\n\n/**\n * Wrap an element so it renders against a message policy (used by `renderEmail`).\n * Returns the element unchanged when no message is given, so the default\n * transactional policy flows through context.\n *\n * Pure — builds a new provider element and does not mutate `element`.\n *\n * @param element - The email element tree to wrap.\n * @param message - The per-send policy; when omitted, `element` is returned unchanged.\n * @returns `element`, wrapped in an {@link EmailMessageContext} provider when a message is given.\n */\nexport function withEmailMessage(element: ReactElement, message?: EmailMessage): ReactElement {\n\tif (!message) return element;\n\treturn createElement(EmailMessageContext.Provider, { value: message }, element);\n}\n\n//#endregion\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,MAAa,oBAAgC;CAC5C,QAAQ,EAAE,GAAG,YAAY;CACzB,OAAO;EACN,SAAS,CAAC,GAAG,WAAW,OAAO,OAAO;EACtC,MAAM,CAAC,GAAG,WAAW,OAAO,IAAI;EAChC,MAAM,CAAC,GAAG,WAAW,OAAO,IAAI;CACjC;CACA,KAAK,EAAE,GAAG,SAAS;CACnB,WAAW,WAAW;AACvB;;;;;;;;;;;;;;AAeA,SAAgB,kBAAkB,MAAkB,UAA2C;CAC9F,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO;EACN,QAAQ;GAAE,GAAG,KAAK;GAAQ,GAAG,SAAS;EAAO;EAC7C,OAAO;GAAE,GAAG,KAAK;GAAO,GAAG,SAAS;EAAM;EAC1C,KAAK;GAAE,GAAG,KAAK;GAAK,GAAG,SAAS;EAAI;EACpC,WAAW,SAAS,cAAc,OAAO,KAAA,IAAa,SAAS,aAAa,KAAK;CAClF;AACD;;;;;;;;;;AAWA,SAAgB,gBAAgB,UAA2C;CAC1E,OAAO,kBAAkB,mBAAmB,QAAQ;AACrD;;;;;;;;;;;AAYA,SAAgB,oBAAoB,OAAmB;CACtD,OAAO;EACN,SAAS,CAAC,gBAAgB;EAC1B,OAAO,EACN,QAAQ;GACP,QAAQ,EAAE,GAAG,MAAM,OAAO;GAC1B,YAAY;IACX,SAAS,CAAC,GAAG,MAAM,MAAM,OAAO;IAChC,MAAM,CAAC,GAAG,MAAM,MAAM,IAAI;IAC1B,MAAM,CAAC,GAAG,MAAM,MAAM,IAAI;GAC3B;EACD,EACD;CACD;AACD;;AAGA,MAAa,oBAAoB,cAA0B,iBAAiB;;;;;;;;;;;;AAa5E,SAAgB,eAAe,SAAuB,UAA6C;CAClG,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,cAAc,kBAAkB,UAAU,EAAE,OAAO,gBAAgB,QAAQ,EAAE,GAAG,OAAO;AAC/F;;AAiBA,MAAa,sBAAsB,cAA4B,EAAE,UAAU,gBAAgB,CAAC;;;;;;;;;;;;AAa5F,SAAgB,iBAAiB,SAAuB,SAAsC;CAC7F,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO,cAAc,oBAAoB,UAAU,EAAE,OAAO,QAAQ,GAAG,OAAO;AAC/E"}
@@ -43,6 +43,7 @@ declare const emailFonts: {
43
43
  };
44
44
  readonly googleFontsHref: "https://fonts.googleapis.com/css2?family=Syne:wght@700;800&family=DM+Sans:wght@400;500&family=DM+Mono:wght@500&display=swap";
45
45
  };
46
+ /** Union of the available email-safe color token names. */
46
47
  type EmailColorToken = keyof typeof emailColors;
47
48
  /**
48
49
  * Organization identity for email chrome (header lockup, signatures, legal
@@ -54,7 +55,7 @@ declare const emailOrg: {
54
55
  readonly productName: "ResQ Tactical OS";
55
56
  readonly legalName: "ResQ Systems, Inc.";
56
57
  readonly registeredAddress: "ResQ Systems, Inc., 131 Continental Dr, Suite 305, Newark, DE 19713, USA";
57
- readonly supportEmail: "support@resq.software";
58
+ readonly supportEmail: "contact@resq.software";
58
59
  readonly websiteUrl: "https://resq.software";
59
60
  readonly termsUrl: "https://resq.software/legal/terms";
60
61
  readonly privacyUrl: "https://resq.software/legal/privacy";
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","names":[],"sources":["../../src/emails/tokens.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;cAwBa;;;;;;;;;;;;;cAGA;;;;;;;;;;;KAED,+BAA+B;;;;;;cAO9B;WACZ;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA"}
1
+ {"version":3,"file":"tokens.d.ts","names":[],"sources":["../../src/emails/tokens.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;cAgCa;;;;;;;;;;;;;cAGA;;;;;;;;;;;;KAGD,+BAA+B;;;;;;cAO9B;WACZ;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA"}
@@ -17,6 +17,13 @@ import { colors, fonts } from "@resq-systems/constants/tokens";
17
17
  * limitations under the License.
18
18
  */
19
19
  /**
20
+ * @fileoverview Email-safe brand tokens — the hex color palette, font stacks, and
21
+ * organization identity, sourced from `@resq-systems/constants` so branding stays
22
+ * centralized across apps.
23
+ *
24
+ * @module @resq-systems/email-templates/emails/tokens
25
+ */
26
+ /**
20
27
  * Email-safe hex color tokens, sourced from the shared `@resq-systems/constants`
21
28
  * design tokens so the brand palette lives in one place across apps. Email
22
29
  * clients don't support `oklch()`, so the hex snapshot is used here.
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","names":[],"sources":["../../src/emails/tokens.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { brand } from \"@resq-systems/constants/brand\";\nimport { colors, fonts } from \"@resq-systems/constants/tokens\";\n\n/**\n * Email-safe hex color tokens, sourced from the shared `@resq-systems/constants`\n * design tokens so the brand palette lives in one place across apps. Email\n * clients don't support `oklch()`, so the hex snapshot is used here.\n */\nexport const emailColors = colors.hex;\n\n/** Brand font stacks + webfont stylesheet href, from the shared design tokens. */\nexport const emailFonts = fonts;\n\nexport type EmailColorToken = keyof typeof emailColors;\n\n/**\n * Organization identity for email chrome (header lockup, signatures, legal\n * footer), derived from the shared `@resq-systems/constants` brand so names,\n * addresses, and legal URLs live in one place across apps.\n */\nexport const emailOrg = {\n\tbrandName: brand.name,\n\tproductName: brand.productName,\n\tlegalName: brand.legalName,\n\tregisteredAddress: brand.postalAddress,\n\tsupportEmail: brand.email.support,\n\twebsiteUrl: brand.domains.marketing,\n\ttermsUrl: brand.legal.termsUrl,\n\tprivacyUrl: brand.legal.privacyUrl,\n\tlogoUrl: brand.logo,\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,cAAc,OAAO;;AAGlC,MAAa,aAAa;;;;;;AAS1B,MAAa,WAAW;CACvB,WAAW,MAAM;CACjB,aAAa,MAAM;CACnB,WAAW,MAAM;CACjB,mBAAmB,MAAM;CACzB,cAAc,MAAM,MAAM;CAC1B,YAAY,MAAM,QAAQ;CAC1B,UAAU,MAAM,MAAM;CACtB,YAAY,MAAM,MAAM;CACxB,SAAS,MAAM;AAChB"}
1
+ {"version":3,"file":"tokens.js","names":[],"sources":["../../src/emails/tokens.ts"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Email-safe brand tokens — the hex color palette, font stacks, and\n * organization identity, sourced from `@resq-systems/constants` so branding stays\n * centralized across apps.\n *\n * @module @resq-systems/email-templates/emails/tokens\n */\n\nimport { brand } from \"@resq-systems/constants/brand\";\nimport { colors, fonts } from \"@resq-systems/constants/tokens\";\n\n/**\n * Email-safe hex color tokens, sourced from the shared `@resq-systems/constants`\n * design tokens so the brand palette lives in one place across apps. Email\n * clients don't support `oklch()`, so the hex snapshot is used here.\n */\nexport const emailColors = colors.hex;\n\n/** Brand font stacks + webfont stylesheet href, from the shared design tokens. */\nexport const emailFonts = fonts;\n\n/** Union of the available email-safe color token names. */\nexport type EmailColorToken = keyof typeof emailColors;\n\n/**\n * Organization identity for email chrome (header lockup, signatures, legal\n * footer), derived from the shared `@resq-systems/constants` brand so names,\n * addresses, and legal URLs live in one place across apps.\n */\nexport const emailOrg = {\n\tbrandName: brand.name,\n\tproductName: brand.productName,\n\tlegalName: brand.legalName,\n\tregisteredAddress: brand.postalAddress,\n\tsupportEmail: brand.email.support,\n\twebsiteUrl: brand.domains.marketing,\n\ttermsUrl: brand.legal.termsUrl,\n\tprivacyUrl: brand.legal.privacyUrl,\n\tlogoUrl: brand.logo,\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,cAAc,OAAO;;AAGlC,MAAa,aAAa;;;;;;AAU1B,MAAa,WAAW;CACvB,WAAW,MAAM;CACjB,aAAa,MAAM;CACnB,WAAW,MAAM;CACjB,mBAAmB,MAAM;CACzB,cAAc,MAAM,MAAM;CAC1B,YAAY,MAAM,QAAQ;CAC1B,UAAU,MAAM,MAAM;CACtB,YAAY,MAAM,MAAM;CACxB,SAAS,MAAM;AAChB"}
@@ -1,5 +1,6 @@
1
1
  import { WelcomeData } from "../schemas.js";
2
2
  //#region src/emails/welcome.d.ts
3
+ /** Props for {@link WelcomeEmail} — the welcome template's validated `data`. */
3
4
  type WelcomeEmailProps = WelcomeData;
4
5
  /** Account welcome / onboarding email. */
5
6
  declare function WelcomeEmail({ firstName, verifyUrl }: WelcomeEmailProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"welcome.d.ts","names":[],"sources":["../../src/emails/welcome.tsx"],"mappings":";;KAmBY,oBAAoB;;iBAGhB,eAAe,WAAqB,aAAa,oCAAiB,IAAA"}
1
+ {"version":3,"file":"welcome.d.ts","names":[],"sources":["../../src/emails/welcome.tsx"],"mappings":";;;KA0BY,oBAAoB;;iBAGhB,eAAe,WAAqB,aAAa,oCAAiB,IAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"welcome.js","names":[],"sources":["../../src/emails/welcome.tsx"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { WelcomeData } from \"../schemas.js\";\nimport { Email } from \"./primitives.js\";\n\nexport type WelcomeEmailProps = WelcomeData;\n\n/** Account welcome / onboarding email. */\nexport function WelcomeEmail({ firstName = \"there\", verifyUrl }: WelcomeEmailProps) {\n\treturn (\n\t\t<Email.Shell preview={`Welcome to ResQ Systems, ${firstName}`}>\n\t\t\t<Email.Header />\n\t\t\t<Email.Title>Welcome to ResQ Systems</Email.Title>\n\t\t\t<Email.Paragraph>Hi {firstName},</Email.Paragraph>\n\t\t\t<Email.Paragraph>\n\t\t\t\tThanks for creating an account. Everything is set up and ready when you are.\n\t\t\t</Email.Paragraph>\n\t\t\t{verifyUrl ? (\n\t\t\t\t<>\n\t\t\t\t\t<Email.Paragraph>\n\t\t\t\t\t\tConfirm your email address to finish setting up your account.\n\t\t\t\t\t</Email.Paragraph>\n\t\t\t\t\t<Email.CTA href={verifyUrl}>Verify email</Email.CTA>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t\t<Email.Signature />\n\t\t\t<Email.LegalFooter\n\t\t\t\tcategory=\"transactional\"\n\t\t\t\treason=\"You are receiving this email because you created a ResQ Systems account.\"\n\t\t\t/>\n\t\t</Email.Shell>\n\t);\n}\n"],"mappings":";;;;AAsBA,SAAgB,aAAa,EAAE,YAAY,SAAS,aAAgC;CACnF,OACC,qBAAC,MAAM,OAAP;EAAa,SAAS,4BAA4B;YAAlD;GACC,oBAAC,MAAM,QAAP,CAAe,CAAA;GACf,oBAAC,MAAM,OAAP,EAAA,UAAa,0BAAoC,CAAA;GACjD,qBAAC,MAAM,WAAP,EAAA,UAAA;IAAiB;IAAI;IAAU;GAAkB,EAAA,CAAA;GACjD,oBAAC,MAAM,WAAP,EAAA,UAAiB,+EAEA,CAAA;GAChB,YACA,qBAAA,UAAA,EAAA,UAAA,CACC,oBAAC,MAAM,WAAP,EAAA,UAAiB,gEAEA,CAAA,GACjB,oBAAC,MAAM,KAAP;IAAW,MAAM;cAAW;GAAuB,CAAA,CAClD,EAAA,CAAA,IACC;GACJ,oBAAC,MAAM,WAAP,CAAkB,CAAA;GAClB,oBAAC,MAAM,aAAP;IACC,UAAS;IACT,QAAO;GACP,CAAA;EACW;;AAEf"}
1
+ {"version":3,"file":"welcome.js","names":[],"sources":["../../src/emails/welcome.tsx"],"sourcesContent":["/**\n * Copyright 2026 ResQ Systems, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Account welcome / onboarding email component.\n *\n * @module @resq-systems/email-templates/emails/welcome\n */\n\nimport type { WelcomeData } from \"../schemas.js\";\nimport { Email } from \"./primitives.js\";\n\n/** Props for {@link WelcomeEmail} — the welcome template's validated `data`. */\nexport type WelcomeEmailProps = WelcomeData;\n\n/** Account welcome / onboarding email. */\nexport function WelcomeEmail({ firstName = \"there\", verifyUrl }: WelcomeEmailProps) {\n\treturn (\n\t\t<Email.Shell preview={`Welcome to ResQ Systems, ${firstName}`}>\n\t\t\t<Email.Header />\n\t\t\t<Email.Title>Welcome to ResQ Systems</Email.Title>\n\t\t\t<Email.Paragraph>Hi {firstName},</Email.Paragraph>\n\t\t\t<Email.Paragraph>\n\t\t\t\tThanks for creating an account. Everything is set up and ready when you are.\n\t\t\t</Email.Paragraph>\n\t\t\t{verifyUrl ? (\n\t\t\t\t<>\n\t\t\t\t\t<Email.Paragraph>\n\t\t\t\t\t\tConfirm your email address to finish setting up your account.\n\t\t\t\t\t</Email.Paragraph>\n\t\t\t\t\t<Email.CTA href={verifyUrl}>Verify email</Email.CTA>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t\t<Email.Signature />\n\t\t\t<Email.LegalFooter\n\t\t\t\tcategory=\"transactional\"\n\t\t\t\treason=\"You are receiving this email because you created a ResQ Systems account.\"\n\t\t\t/>\n\t\t</Email.Shell>\n\t);\n}\n"],"mappings":";;;;AA6BA,SAAgB,aAAa,EAAE,YAAY,SAAS,aAAgC;CACnF,OACC,qBAAC,MAAM,OAAP;EAAa,SAAS,4BAA4B;EAAlD,UAAA;GACC,oBAAC,MAAM,QAAP,CAAe,CAAA;GACf,oBAAC,MAAM,OAAP,EAAA,UAAa,0BAAoC,CAAA;GACjD,qBAAC,MAAM,WAAP,EAAA,UAAA;IAAiB;IAAI;IAAU;GAAkB,EAAA,CAAA;GACjD,oBAAC,MAAM,WAAP,EAAA,UAAiB,+EAEA,CAAA;GAChB,YACA,qBAAA,UAAA,EAAA,UAAA,CACC,oBAAC,MAAM,WAAP,EAAA,UAAiB,gEAEA,CAAA,GACjB,oBAAC,MAAM,KAAP;IAAW,MAAM;IAAW,UAAA;GAAuB,CAAA,CAClD,EAAA,CAAA,IACC;GACJ,oBAAC,MAAM,WAAP,CAAkB,CAAA;GAClB,oBAAC,MAAM,aAAP;IACC,UAAS;IACT,QAAO;GACP,CAAA;EACW;;AAEf"}
package/lib/index.d.ts CHANGED
@@ -5,4 +5,4 @@ import { EmailName, EmailPayload, EmailTemplateData, decodeEmailPayload } from "
5
5
  import { registry } from "./registry.js";
6
6
  import { renderEmail } from "./render.js";
7
7
  import { incidentAlertTemplate, missionApprovalTemplate, newDeviceLoginTemplate, notificationTemplate, orgInvitationTemplate, otpTemplate, passwordChangedTemplate, passwordResetTemplate, resqEmailTemplates, welcomeTemplate } from "./templates.js";
8
- export { EmailAddress, EmailCategory, EmailMessage, EmailMessageContext, EmailName, EmailOrgIdentity, EmailPayload, type EmailRegistryEntry, EmailTemplateData, type EmailTemplateDef, EmailTheme, EmailThemeContext, EmailThemeFonts, EmailThemeOverride, EmailValidationError, HttpUrl, IncidentAlertData, type Mailer, type MailerPayload, type MailerTemplateData, MissionApprovalData, NewDeviceLoginData, NotificationData, OrgInvitationData, OtpData, PasswordChangedData, PasswordResetData, type RenderEmailOptions, type RenderedEmail, WelcomeData, buildTailwindConfig, createMailer, decodeEmailPayload, defaultEmailTheme, defineEmailTemplate, emailCategory, incidentAlertData, incidentAlertTemplate, mergeEmailTheme, missionApprovalData, missionApprovalTemplate, newDeviceLoginData, newDeviceLoginTemplate, notificationData, notificationTemplate, orgInvitationData, orgInvitationTemplate, otpData, otpTemplate, passwordChangedData, passwordChangedTemplate, passwordResetData, passwordResetTemplate, registry, renderEmail, resolveEmailTheme, resqEmailTemplates, welcomeData, welcomeTemplate, withEmailMessage, withEmailTheme };
8
+ export { EmailAddress, type EmailCategory, type EmailMessage, EmailMessageContext, type EmailName, type EmailOrgIdentity, EmailPayload, type EmailRegistryEntry, type EmailTemplateData, type EmailTemplateDef, type EmailTheme, EmailThemeContext, type EmailThemeFonts, type EmailThemeOverride, EmailValidationError, HttpUrl, type IncidentAlertData, type Mailer, type MailerPayload, type MailerTemplateData, type MissionApprovalData, type NewDeviceLoginData, type NotificationData, type OrgInvitationData, type OtpData, type PasswordChangedData, type PasswordResetData, type RenderEmailOptions, type RenderedEmail, type WelcomeData, buildTailwindConfig, createMailer, decodeEmailPayload, defaultEmailTheme, defineEmailTemplate, emailCategory, incidentAlertData, incidentAlertTemplate, mergeEmailTheme, missionApprovalData, missionApprovalTemplate, newDeviceLoginData, newDeviceLoginTemplate, notificationData, notificationTemplate, orgInvitationData, orgInvitationTemplate, otpData, otpTemplate, passwordChangedData, passwordChangedTemplate, passwordResetData, passwordResetTemplate, registry, renderEmail, resolveEmailTheme, resqEmailTemplates, welcomeData, welcomeTemplate, withEmailMessage, withEmailTheme };
package/lib/mailer.d.ts CHANGED
@@ -3,14 +3,42 @@ import { EmailThemeOverride } from "./emails/theme.js";
3
3
  import { Schema } from "effect";
4
4
  import { ReactElement } from "react";
5
5
  //#region src/mailer.d.ts
6
- /** A template definition: its name, `data` schema, subject line, and component. */
6
+ /**
7
+ * A template definition: its discriminant {@link EmailTemplateDef.name}, `data`
8
+ * schema, subject builder, and React component.
9
+ *
10
+ * `name` must be unique across the defs handed to {@link createMailer} — it is the
11
+ * payload union's discriminant, and a later def with a duplicate name silently
12
+ * overwrites the earlier one in the registry (last write wins in
13
+ * `Object.fromEntries`). `subject` and `Component` are only ever invoked with data
14
+ * that has already cleared `data`'s schema at the decode boundary, so they may
15
+ * treat every field as valid and should stay pure.
16
+ *
17
+ * @template Name - The literal template name (e.g. `"otp"`); the payload discriminant.
18
+ * @template DataSchema - The Effect Schema whose decoded `Type` is this template's `data`.
19
+ */
7
20
  interface EmailTemplateDef<Name extends string, DataSchema extends Schema.Top> {
21
+ /** Unique template name; the payload union's discriminant. */
8
22
  readonly name: Name;
23
+ /** Effect Schema that validates this template's `data` at the decode boundary. */
9
24
  readonly data: DataSchema;
25
+ /** Builds the subject line from already-validated `data`. Should be pure. */
10
26
  readonly subject: (data: DataSchema["Type"]) => string;
27
+ /** Renders the email body from already-validated `data`. */
11
28
  readonly Component: (data: DataSchema["Type"]) => ReactElement;
12
29
  }
13
- /** Identity helper that infers and preserves a template def's literal types. */
30
+ /**
31
+ * Identity helper that infers and preserves a template def's literal types.
32
+ *
33
+ * Pure — returns `def` by reference, unchanged. It exists only so the `const` type
34
+ * parameters capture the literal `name` and the schema's `Type` at the call site;
35
+ * a bare object literal would widen `name` to `string` and lose the discriminant.
36
+ *
37
+ * @template Name - The literal template name; preserved via the `const` modifier.
38
+ * @template DataSchema - The template's `data` schema.
39
+ * @param def - The template definition to brand with its inferred literal types.
40
+ * @returns The same `def` object, typed with its narrowed literals.
41
+ */
14
42
  declare function defineEmailTemplate<const Name extends string, DataSchema extends Schema.Top>(def: EmailTemplateDef<Name, DataSchema>): EmailTemplateDef<Name, DataSchema>;
15
43
  /**
16
44
  * The common supertype for a heterogeneous list of template defs. The `never`
@@ -34,18 +62,38 @@ type PayloadFor<Def> = Def extends EmailTemplateDef<infer Name, infer DataSchema
34
62
  /** Unsubscribe/preferences URL, surfaced in the legal footer for `marketing`. */
35
63
  readonly unsubscribeUrl?: string;
36
64
  } : never;
37
- /** The discriminated payload union for a tuple of template defs. */
65
+ /**
66
+ * The discriminated payload union for a tuple of template defs — one
67
+ * `{ name, to, data, category?, unsubscribeUrl? }` variant per def, discriminated
68
+ * by the literal `name` field. Narrow a value with `payload.name` to recover the
69
+ * matching `data` type.
70
+ *
71
+ * @template Defs - The `as const` tuple of template defs the union is built over.
72
+ */
38
73
  type MailerPayload<Defs extends readonly AnyTemplateDef[]> = PayloadFor<Defs[number]>;
39
- /** The `data` type for a given template name within a set of defs. */
74
+ /**
75
+ * The `data` type for a given template name within a set of defs — the `data`
76
+ * field of the {@link MailerPayload} variant whose discriminant equals `Name`.
77
+ *
78
+ * @template Defs - The tuple of template defs the payload union is built over.
79
+ * @template Name - The literal `name` selecting a single variant's `data` shape.
80
+ */
40
81
  type MailerTemplateData<Defs extends readonly AnyTemplateDef[], Name extends MailerPayload<Defs>["name"]> = Extract<MailerPayload<Defs>, {
41
82
  name: Name;
42
83
  }>["data"];
43
- /** The rendered, provider-ready email. */
84
+ /**
85
+ * The rendered, provider-ready email — the resolved output of
86
+ * {@link Mailer.renderEmail}. `html` and `text` are two renderings of the *same*
87
+ * message, so a provider may attach both as a multipart alternative.
88
+ */
44
89
  interface RenderedEmail {
45
- /** Validated recipient (branded {@link EmailAddress}), carried from decode. */
90
+ /** Validated recipient (branded {@link EmailAddress}), carried through from decode. */
46
91
  to: EmailAddress;
92
+ /** The subject line produced by the template's `subject` builder. */
47
93
  subject: string;
94
+ /** The complete standalone HTML document for the email body. */
48
95
  html: string;
96
+ /** The plain-text alternative rendering of the same body, for text-only clients. */
49
97
  text: string;
50
98
  }
51
99
  /** Options for a mailer's `renderEmail`. */
@@ -53,13 +101,30 @@ interface RenderEmailOptions {
53
101
  /** Rebrand this render by overriding theme colors/fonts (see `EmailThemeOverride`). */
54
102
  theme?: EmailThemeOverride;
55
103
  }
56
- /** Thrown when an untrusted payload fails schema validation at the boundary. */
104
+ /**
105
+ * Thrown when an untrusted payload fails schema validation at the decode boundary
106
+ * ({@link Mailer.decode}, and transitively {@link Mailer.renderEmail}).
107
+ *
108
+ * The `message` is the squashed Effect `Cause` from the failed decode; `name` is
109
+ * the stable literal `"EmailValidationError"`, so a caller can tell a bad payload
110
+ * apart from other failures by `name` without relying on `instanceof` across
111
+ * module/realm boundaries.
112
+ */
57
113
  declare class EmailValidationError extends Error {
58
114
  readonly name = "EmailValidationError";
59
115
  }
60
- /** A registry entry: the subject builder and component renderer for one template. */
116
+ /**
117
+ * A registry entry: the subject builder and component renderer for one template.
118
+ *
119
+ * Both functions take `unknown` because the registry is keyed by name and has
120
+ * erased each def's `data` type. They must only be called with data that has
121
+ * already passed that template's schema (as {@link Mailer.renderEmail} does after
122
+ * {@link Mailer.decode}); calling them with unvalidated data is unsound.
123
+ */
61
124
  interface EmailRegistryEntry {
125
+ /** Builds the subject from validated `data` (typed `unknown` after name-erasure). */
62
126
  subject: (data: unknown) => string;
127
+ /** Renders the body element from validated `data` (typed `unknown` after name-erasure). */
63
128
  render: (data: unknown) => ReactElement;
64
129
  }
65
130
  /** A composed set of templates: contract schema, decoder, registry, and renderer. */
@@ -72,11 +137,33 @@ interface Mailer<Payload extends {
72
137
  readonly schema: Schema.Top;
73
138
  /** name → { subject, render } for every template. */
74
139
  readonly registry: Record<Payload["name"], EmailRegistryEntry>;
75
- /** Every registered template name. */
140
+ /** Every registered template name, in def order. */
76
141
  readonly names: readonly Payload["name"][];
77
- /** Validate an untrusted payload (throws {@link EmailValidationError}). */
142
+ /**
143
+ * Validate an untrusted payload against the contract union and return the
144
+ * narrowed {@link Payload}.
145
+ *
146
+ * @param input - Untrusted `{ name, to, data }` value from the boundary.
147
+ * @returns The validated, branded payload.
148
+ * @throws {EmailValidationError} If `input` matches no template variant — bad
149
+ * `name`, a malformed/header-injecting `to`, or `data` failing its schema.
150
+ */
78
151
  decode(input: unknown): Payload;
79
- /** Validate then render to `{ to, subject, html, text }` (headless, pipeline-safe). */
152
+ /**
153
+ * Validate then render a payload to `{ to, subject, html, text }`.
154
+ *
155
+ * Validates via {@link decode} first, then renders headlessly through
156
+ * `@react-email/render` — no browser, DOM, network, or clock — so it is safe in
157
+ * queue workers and cron jobs. Pure and stateless: concurrent calls against one
158
+ * mailer do not interfere, and there is no ordering guarantee between them. Does
159
+ * not honour an `AbortSignal`.
160
+ *
161
+ * @param input - Untrusted payload to validate and render.
162
+ * @param options - Optional per-render theme override.
163
+ * @returns A promise resolving to the rendered email.
164
+ * @throws {EmailValidationError} As a rejected promise, when `input` fails
165
+ * validation (surfaced from {@link decode}).
166
+ */
80
167
  renderEmail(input: unknown, options?: RenderEmailOptions): Promise<RenderedEmail>;
81
168
  }
82
169
  /**
@@ -84,6 +171,26 @@ interface Mailer<Payload extends {
84
171
  * `{ name, to, data }` contract, a boundary decoder, a registry, and a headless
85
172
  * renderer. Spread the built-in `resqEmailTemplates` and add your own — each
86
173
  * template's `data` is validated by its Effect Schema.
174
+ *
175
+ * Pure: builds the schema union and registry eagerly and holds no mutable state;
176
+ * the returned `decode`/`renderEmail` are the only fallible surfaces. `defs`
177
+ * should have unique `name`s — a duplicate makes the later def win in the registry
178
+ * while both remain in the schema union (see {@link EmailTemplateDef}).
179
+ *
180
+ * @template Defs - The `as const` tuple of template defs to compose.
181
+ * @param defs - The template definitions; pass `[...resqEmailTemplates, myDef]` to extend the built-ins.
182
+ * @returns A {@link Mailer} whose `decode` throws (and `renderEmail` rejects with)
183
+ * {@link EmailValidationError} on invalid input.
184
+ * @example
185
+ * ```ts
186
+ * const mailer = createMailer(resqEmailTemplates);
187
+ * const { subject } = await mailer.renderEmail({
188
+ * name: "otp",
189
+ * to: "user@example.com",
190
+ * data: { code: "123456" },
191
+ * });
192
+ * subject; // → "Your ResQ Systems verification code: 123456"
193
+ * ```
87
194
  */
88
195
  declare function createMailer<const Defs extends readonly AnyTemplateDef[]>(defs: Defs): Mailer<MailerPayload<Defs>>;
89
196
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"mailer.d.ts","names":[],"sources":["../src/mailer.tsx"],"mappings":";;;;;;UAoCiB,iBAAiB,qBAAqB,mBAAmB,OAAO;WACvE,MAAM;WACN,MAAM;WACN,UAAU,MAAM;WAChB,YAAY,MAAM,uBAAuB;;;iBAInC,0BAA0B,qBAAqB,mBAAmB,OAAO,KACxF,KAAK,iBAAiB,MAAM,cAC1B,iBAAiB,MAAM;;;;;;;UAUhB;WACA;WACA,MAAM,OAAO;WACb,UAAU;WACV,YAAY,gBAAgB;;;KAIjC,WAAW,OACf,YAAY,uBAAuB,YAAY;WAEnC,MAAM;WACN,IAAI;WACJ,MAAM;;WAEN;;WAEA;;;KAKD,cAAc,sBAAsB,oBAAoB,WAAW;;KAGnE,mBACX,sBAAsB,kBACtB,aAAa,cAAc,iBACxB,QAAQ,cAAc;EAAS,MAAM;;;UAGxB;;EAEhB,IAAI;EACJ;EACA;EACA;;;UAIgB;;EAEhB,QAAQ;;;cAII,6BAA6B;WACvB;;;UAIF;EAChB,UAAU;EACV,SAAS,kBAAkB;;;UAIX,OAChB;WAA2B;WAAuB;WAAqB;;;WAG9D,QAAQ,OAAO;;WAEf,UAAU,OAAO,iBAAiB;;WAElC,gBAAgB;;EAEzB,OAAO,iBAAiB;;EAExB,YAAY,gBAAgB,UAAU,qBAAqB,QAAQ;;;;;;;;iBASpD,mBAAmB,sBAAsB,kBACxD,MAAM,OACJ,OAAO,cAAc"}
1
+ {"version":3,"file":"mailer.d.ts","names":[],"sources":["../src/mailer.tsx"],"mappings":";;;;;;;;;;;;;;;;;;;UA+DiB,iBAAiB,qBAAqB,mBAAmB,OAAO;;WAEvE,MAAM;;WAEN,MAAM;;WAEN,UAAU,MAAM;;WAEhB,YAAY,MAAM,uBAAuB;;;;;;;;;;;;;;iBAenC,0BAA0B,qBAAqB,mBAAmB,OAAO,KACxF,KAAK,iBAAiB,MAAM,cAC1B,iBAAiB,MAAM;;;;;;;UAUhB;WACA;WACA,MAAM,OAAO;WACb,UAAU;WACV,YAAY,gBAAgB;;;KAIjC,WAAW,OACf,YAAY,uBAAuB,YAAY;WAEnC,MAAM;WACN,IAAI;WACJ,MAAM;;WAEN;;WAEA;;;;;;;;;;KAYD,cAAc,sBAAsB,oBAAoB,WAAW;;;;;;;;KASnE,mBACX,sBAAsB,kBACtB,aAAa,cAAc,iBACxB,QAAQ,cAAc;EAAS,MAAM;;;;;;;UAOxB;;EAEhB,IAAI;;EAEJ;;EAEA;;EAEA;;;UAIgB;;EAEhB,QAAQ;;;;;;;;;;;cAYI,6BAA6B;WACvB;;;;;;;;;;UAWF;;EAEhB,UAAU;;EAEV,SAAS,kBAAkB;;;UAIX,OAChB;WAA2B;WAAuB;WAAqB;;;WAG9D,QAAQ,OAAO;;WAEf,UAAU,OAAO,iBAAiB;;WAElC,gBAAgB;;;;;;;;;;EAUzB,OAAO,iBAAiB;;;;;;;;;;;;;;;;EAgBxB,YAAY,gBAAgB,UAAU,qBAAqB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiCpD,mBAAmB,sBAAsB,kBACxD,MAAM,OACJ,OAAO,cAAc"}