@headless-lms/adapter-email-templates 0.1.0 โ†’ 0.2.1

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/index.js CHANGED
@@ -1,21 +1,20 @@
1
1
  import { render } from "@react-email/render";
2
- import { Body, Button, Container, Head, Heading, Hr, Html, Img, Link, Section, Tailwind, Text } from "@react-email/components";
2
+ import { Body, Button, Column, Container, Head, Heading, Hr, Html, Img, Link, Row, Section, Tailwind, Text } from "@react-email/components";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/emails/layout.tsx
5
+ const LOGO_URL = "https://headless-lms.dev/logo.png";
6
+ const ICON_URL = "https://headless-lms.dev/apple-icon";
5
7
  function Layout({ ctx, heading, children }) {
6
8
  return /* @__PURE__ */ jsx(Html, { children: /* @__PURE__ */ jsxs(Tailwind, { children: [/* @__PURE__ */ jsx(Head, {}), /* @__PURE__ */ jsx(Body, {
7
9
  className: "bg-white font-sans",
8
10
  children: /* @__PURE__ */ jsxs(Container, {
9
11
  className: "mx-auto max-w-[560px] px-6 pt-5 pb-12",
10
12
  children: [
11
- ctx.logoUrl ? /* @__PURE__ */ jsx(Img, {
12
- src: ctx.logoUrl,
13
+ /* @__PURE__ */ jsx(Img, {
14
+ src: LOGO_URL,
13
15
  alt: ctx.brandName,
14
- height: 42,
15
- className: "h-[42px]"
16
- }) : /* @__PURE__ */ jsx(Text, {
17
- className: "m-0 text-[15px] font-semibold text-[#3c4149]",
18
- children: ctx.brandName
16
+ height: 32,
17
+ className: "h-[32px]"
19
18
  }),
20
19
  /* @__PURE__ */ jsx(Heading, {
21
20
  className: "mt-[28px] mb-0 text-[24px] font-normal leading-[1.3] tracking-[-0.5px] text-[#484848]",
@@ -23,11 +22,23 @@ function Layout({ ctx, heading, children }) {
23
22
  }),
24
23
  /* @__PURE__ */ jsx(Section, { children }),
25
24
  /* @__PURE__ */ jsx(Hr, { className: "mt-[42px] mb-[26px] border-[#dfe1e4]" }),
26
- /* @__PURE__ */ jsx(Link, {
27
- href: ctx.baseUrl,
28
- className: "text-[14px] text-[#b4becc]",
29
- children: ctx.brandName
30
- })
25
+ /* @__PURE__ */ jsxs(Row, { children: [/* @__PURE__ */ jsx(Column, {
26
+ className: "w-[24px]",
27
+ children: /* @__PURE__ */ jsx(Img, {
28
+ src: ICON_URL,
29
+ alt: "",
30
+ width: 24,
31
+ height: 24,
32
+ className: "rounded-[6px]"
33
+ })
34
+ }), /* @__PURE__ */ jsx(Column, {
35
+ className: "pl-[8px]",
36
+ children: /* @__PURE__ */ jsx(Link, {
37
+ href: ctx.baseUrl,
38
+ className: "text-[14px] text-[#b4becc]",
39
+ children: ctx.brandName
40
+ })
41
+ })] })
31
42
  ]
32
43
  })
33
44
  })] }) });
@@ -55,7 +66,7 @@ const PREVIEW_CTX = {
55
66
  };
56
67
  //#endregion
57
68
  //#region src/emails/magic-link.tsx
58
- const subject$7 = (ctx, _params) => `Sign in to ${ctx.brandName}`;
69
+ const subject$8 = (ctx, _params) => `Sign in to ${ctx.brandName}`;
59
70
  function MagicLink({ ctx, params }) {
60
71
  return /* @__PURE__ */ jsxs(Layout, {
61
72
  ctx,
@@ -76,7 +87,7 @@ MagicLink.PreviewProps = {
76
87
  };
77
88
  //#endregion
78
89
  //#region src/emails/student-invite.tsx
79
- const subject$6 = (ctx, _params) => `You're invited to ${ctx.brandName}`;
90
+ const subject$7 = (ctx, _params) => `You're invited to ${ctx.brandName}`;
80
91
  function StudentInvite({ ctx, params }) {
81
92
  return /* @__PURE__ */ jsxs(Layout, {
82
93
  ctx,
@@ -105,7 +116,7 @@ StudentInvite.PreviewProps = {
105
116
  };
106
117
  //#endregion
107
118
  //#region src/emails/member-invite.tsx
108
- const subject$5 = (ctx, _params) => `You've been invited to join ${ctx.brandName}`;
119
+ const subject$6 = (ctx, _params) => `You've been invited to join ${ctx.brandName}`;
109
120
  function MemberInvite({ ctx, params }) {
110
121
  return /* @__PURE__ */ jsxs(Layout, {
111
122
  ctx,
@@ -132,12 +143,12 @@ MemberInvite.PreviewProps = {
132
143
  params: {
133
144
  inviteUrl: "http://localhost:8001/invite?token=demo",
134
145
  inviterName: "Ann",
135
- role: "admin"
146
+ role: "Admin"
136
147
  }
137
148
  };
138
149
  //#endregion
139
150
  //#region src/emails/password-reset.tsx
140
- const subject$4 = (ctx, _params) => `Reset your ${ctx.brandName} password`;
151
+ const subject$5 = (ctx, _params) => `Reset your ${ctx.brandName} password`;
141
152
  function PasswordReset({ ctx, params }) {
142
153
  return /* @__PURE__ */ jsxs(Layout, {
143
154
  ctx,
@@ -157,6 +168,24 @@ PasswordReset.PreviewProps = {
157
168
  params: { resetUrl: "http://localhost:8002/reset?token=demo" }
158
169
  };
159
170
  //#endregion
171
+ //#region src/emails/password-changed.tsx
172
+ const subject$4 = (ctx, _params) => `Your ${ctx.brandName} password was changed`;
173
+ function PasswordChanged({ ctx }) {
174
+ return /* @__PURE__ */ jsxs(Layout, {
175
+ ctx,
176
+ heading: "Your password was changed",
177
+ children: [/* @__PURE__ */ jsxs(Paragraph, { children: [
178
+ "The password for your ",
179
+ ctx.brandName,
180
+ " account was just changed."
181
+ ] }), /* @__PURE__ */ jsx(Paragraph, { children: "If you didn't make this change, reply to this email right away." })]
182
+ });
183
+ }
184
+ PasswordChanged.PreviewProps = {
185
+ ctx: PREVIEW_CTX,
186
+ params: {}
187
+ };
188
+ //#endregion
160
189
  //#region src/emails/email-verification.tsx
161
190
  const subject$3 = (ctx, _params) => `Verify your email for ${ctx.brandName}`;
162
191
  function EmailVerification({ ctx, params }) {
@@ -176,13 +205,29 @@ EmailVerification.PreviewProps = {
176
205
  //#endregion
177
206
  //#region src/emails/access-granted.tsx
178
207
  const subject$2 = (_ctx, params) => `You now have access to ${params.contentTitle}`;
208
+ const PORTAL_PATH = {
209
+ course: "courses",
210
+ download: "downloads",
211
+ community: "communities",
212
+ event: "events"
213
+ };
214
+ const BUTTON = {
215
+ course: "Start learning",
216
+ download: "View download",
217
+ community: "Open community",
218
+ event: "Open event",
219
+ bundle: "Open your library"
220
+ };
221
+ function hrefOf(ctx, params) {
222
+ return params.contentType === "bundle" ? ctx.studentPortalUrl : `${ctx.studentPortalUrl}/${PORTAL_PATH[params.contentType]}/${params.contentId}`;
223
+ }
179
224
  function AccessGranted({ ctx, params }) {
180
225
  return /* @__PURE__ */ jsxs(Layout, {
181
226
  ctx,
182
227
  heading: `${params.contentTitle} is ready for you`,
183
- children: [/* @__PURE__ */ jsx(Paragraph, { children: "You've been granted access. Jump in whenever you're ready." }), /* @__PURE__ */ jsx(EmailButton, {
184
- href: `${ctx.studentPortalUrl}/courses/${params.contentId}`,
185
- children: "Start learning"
228
+ children: [/* @__PURE__ */ jsx(Paragraph, { children: params.contentType === "bundle" ? "You've been granted access to everything it includes. Jump in whenever you're ready." : "You've been granted access. Jump in whenever you're ready." }), /* @__PURE__ */ jsx(EmailButton, {
229
+ href: hrefOf(ctx, params),
230
+ children: BUTTON[params.contentType]
186
231
  })]
187
232
  });
188
233
  }
@@ -190,7 +235,8 @@ AccessGranted.PreviewProps = {
190
235
  ctx: PREVIEW_CTX,
191
236
  params: {
192
237
  contentTitle: "Fly Tying 101",
193
- contentId: "demo"
238
+ contentId: "demo",
239
+ contentType: "course"
194
240
  }
195
241
  };
196
242
  //#endregion
@@ -230,24 +276,761 @@ CourseCompleted.PreviewProps = {
230
276
  params: { courseTitle: "Fly Tying 101" }
231
277
  };
232
278
  //#endregion
279
+ //#region src/emails/community.tsx
280
+ function portal(ctx, path) {
281
+ return `${ctx.studentPortalUrl}${path}`;
282
+ }
283
+ function defineEmail(opts) {
284
+ function Component({ ctx, params }) {
285
+ const button = opts.button?.(ctx, params);
286
+ return /* @__PURE__ */ jsxs(Layout, {
287
+ ctx,
288
+ heading: opts.heading(params),
289
+ children: [opts.lines(params).map((line, index) => /* @__PURE__ */ jsx(Paragraph, { children: line }, index)), button ? /* @__PURE__ */ jsx(EmailButton, {
290
+ href: button.href,
291
+ children: button.label
292
+ }) : null]
293
+ });
294
+ }
295
+ Component.PreviewProps = {
296
+ ctx: PREVIEW_CTX,
297
+ params: opts.preview
298
+ };
299
+ return {
300
+ subject: opts.subject,
301
+ Component
302
+ };
303
+ }
304
+ const community = (ctx, id) => portal(ctx, `/communities/${id}`);
305
+ const space = (ctx, communityId, spaceId) => portal(ctx, `/communities/${communityId}/spaces/${spaceId}`);
306
+ const post = (ctx, communityId, postId) => portal(ctx, `/communities/${communityId}/posts/${postId}`);
307
+ const comment = (ctx, communityId, postId, commentId) => `${post(ctx, communityId, postId)}#${commentId}`;
308
+ const chat = (ctx, communityId, chatId) => portal(ctx, `/communities/${communityId}/chats/${chatId}`);
309
+ function accessEnds(value) {
310
+ const date = new Date(value);
311
+ if (Number.isNaN(date.getTime())) return value;
312
+ return new Intl.DateTimeFormat("en-US", {
313
+ day: "numeric",
314
+ month: "long",
315
+ year: "numeric",
316
+ timeZone: "UTC"
317
+ }).format(date);
318
+ }
319
+ const welcomeToCommunity = defineEmail({
320
+ subject: (_ctx, params) => `Welcome to ${params.communityTitle}`,
321
+ heading: (params) => params.communityTitle,
322
+ lines: (params) => [params.spaceNames.length > 0 ? `You can open ${params.spaceNames.join(", ")}.` : "You're a member."],
323
+ button: (ctx, params) => ({
324
+ href: community(ctx, params.communityId),
325
+ label: "Open community"
326
+ }),
327
+ preview: {
328
+ communityTitle: "Founders",
329
+ communityId: "cmy_1",
330
+ spaceNames: ["Announcements"]
331
+ }
332
+ });
333
+ const membershipEndingSoon = defineEmail({
334
+ subject: (_ctx, params) => `${params.communityTitle} ends soon`,
335
+ heading: (params) => `${params.communityTitle} ends soon`,
336
+ lines: (params) => [`Your access ends ${accessEnds(params.expiresAt)}.`],
337
+ button: (ctx, params) => ({
338
+ href: community(ctx, params.communityId),
339
+ label: "Renew"
340
+ }),
341
+ preview: {
342
+ communityTitle: "Founders",
343
+ communityId: "cmy_1",
344
+ expiresAt: "2026-10-28T00:00:00.000Z"
345
+ }
346
+ });
347
+ function communityTitles(params) {
348
+ return params.communities.map((item) => item.communityTitle).join(", ");
349
+ }
350
+ const membershipEnded = defineEmail({
351
+ subject: (_ctx, params) => `${communityTitles(params)} has ended`,
352
+ heading: (params) => `${communityTitles(params)} has ended`,
353
+ lines: (params) => [params.communities.length === 1 ? "Your access to this community has ended." : "Your access to these communities has ended."],
354
+ button: (ctx, params) => {
355
+ const [only] = params.communities;
356
+ return params.communities.length === 1 && only ? {
357
+ href: community(ctx, only.communityId),
358
+ label: "Renew"
359
+ } : {
360
+ href: portal(ctx, "/communities"),
361
+ label: "Open communities"
362
+ };
363
+ },
364
+ preview: { communities: [{
365
+ communityId: "cmy_1",
366
+ communityTitle: "Founders"
367
+ }] }
368
+ });
369
+ const newPostInSpace = defineEmail({
370
+ subject: (_ctx, params) => `${params.authorName} posted in ${params.spaceName}`,
371
+ heading: (params) => params.postTitle,
372
+ lines: (params) => [`${params.authorName} in ${params.spaceName}`, params.excerpt],
373
+ button: (ctx, params) => ({
374
+ href: post(ctx, params.communityId, params.postId),
375
+ label: "Read post"
376
+ }),
377
+ preview: {
378
+ spaceName: "Announcements",
379
+ postTitle: "Hello",
380
+ authorName: "Ann",
381
+ excerpt: "A short note",
382
+ postId: "pst_1",
383
+ communityId: "cmy_1"
384
+ }
385
+ });
386
+ const yourPostWasPublished = defineEmail({
387
+ subject: (_ctx, params) => `Your post was published in ${params.spaceName}`,
388
+ heading: (params) => params.postTitle,
389
+ lines: (params) => [`It's live in ${params.spaceName}.`],
390
+ button: (ctx, params) => ({
391
+ href: post(ctx, params.communityId, params.postId),
392
+ label: "View post"
393
+ }),
394
+ preview: {
395
+ postTitle: "Hello",
396
+ spaceName: "Announcements",
397
+ postId: "pst_1",
398
+ communityId: "cmy_1"
399
+ }
400
+ });
401
+ const yourPostWasRemoved = defineEmail({
402
+ subject: (_ctx, params) => `Your post was removed from ${params.spaceName}`,
403
+ heading: (params) => params.postTitle,
404
+ lines: (params) => [`It was removed from ${params.spaceName}.`],
405
+ button: (ctx, params) => ({
406
+ href: space(ctx, params.communityId, params.spaceId),
407
+ label: "Open space"
408
+ }),
409
+ preview: {
410
+ postTitle: "Hello",
411
+ spaceName: "Announcements",
412
+ spaceId: "spc_1",
413
+ communityId: "cmy_1"
414
+ }
415
+ });
416
+ const newCommentOnPost = defineEmail({
417
+ subject: (_ctx, params) => `${params.commenterName} commented on ${params.postTitle}`,
418
+ heading: (params) => params.postTitle,
419
+ lines: (params) => [params.commenterName, params.excerpt],
420
+ button: (ctx, params) => ({
421
+ href: comment(ctx, params.communityId, params.postId, params.commentId),
422
+ label: "View comment"
423
+ }),
424
+ preview: {
425
+ postTitle: "Hello",
426
+ commenterName: "Sam",
427
+ excerpt: "Nice",
428
+ commentId: "cmt_1",
429
+ postId: "pst_1",
430
+ communityId: "cmy_1"
431
+ }
432
+ });
433
+ const replyToYourComment = defineEmail({
434
+ subject: (_ctx, params) => `${params.commenterName} replied on ${params.postTitle}`,
435
+ heading: (params) => params.postTitle,
436
+ lines: (params) => [params.commenterName, params.excerpt],
437
+ button: (ctx, params) => ({
438
+ href: comment(ctx, params.communityId, params.postId, params.commentId),
439
+ label: "View reply"
440
+ }),
441
+ preview: {
442
+ postTitle: "Hello",
443
+ commenterName: "Sam",
444
+ excerpt: "Thanks",
445
+ commentId: "cmt_2",
446
+ postId: "pst_1",
447
+ communityId: "cmy_1"
448
+ }
449
+ });
450
+ const yourCommentWasRemoved = defineEmail({
451
+ subject: (_ctx, params) => `Your comment was removed from ${params.postTitle}`,
452
+ heading: (params) => params.postTitle,
453
+ lines: () => ["Your comment was removed."],
454
+ button: (ctx, params) => ({
455
+ href: post(ctx, params.communityId, params.postId),
456
+ label: "View post"
457
+ }),
458
+ preview: {
459
+ postTitle: "Hello",
460
+ postId: "pst_1",
461
+ communityId: "cmy_1"
462
+ }
463
+ });
464
+ const requestApproved = defineEmail({
465
+ subject: (_ctx, params) => `You're in ${params.spaceName}`,
466
+ heading: (params) => params.spaceName,
467
+ lines: (params) => [`Your request to join ${params.spaceName} was approved.`],
468
+ button: (ctx, params) => ({
469
+ href: space(ctx, params.communityId, params.spaceId),
470
+ label: "Open space"
471
+ }),
472
+ preview: {
473
+ spaceName: "SaaS",
474
+ spaceId: "spc_1",
475
+ communityId: "cmy_1"
476
+ }
477
+ });
478
+ const requestDeclined = defineEmail({
479
+ subject: (_ctx, params) => `Request declined for ${params.spaceName}`,
480
+ heading: (params) => params.spaceName,
481
+ lines: (params) => [`Your request to join ${params.spaceName} was declined.`],
482
+ button: (ctx, params) => ({
483
+ href: community(ctx, params.communityId),
484
+ label: "Open community"
485
+ }),
486
+ preview: {
487
+ spaceName: "SaaS",
488
+ communityId: "cmy_1"
489
+ }
490
+ });
491
+ const invitedToSpace = defineEmail({
492
+ subject: (_ctx, params) => `${params.inviterName} invited you to ${params.spaceName}`,
493
+ heading: (params) => params.spaceName,
494
+ lines: (params) => [`${params.inviterName} invited you.`],
495
+ button: (ctx, params) => ({
496
+ href: space(ctx, params.communityId, params.spaceId),
497
+ label: "Accept"
498
+ }),
499
+ preview: {
500
+ spaceName: "SaaS",
501
+ inviterName: "Ann",
502
+ spaceId: "spc_1",
503
+ communityId: "cmy_1"
504
+ }
505
+ });
506
+ const messageRequest = defineEmail({
507
+ subject: (_ctx, params) => `${params.senderName} sent a message request`,
508
+ heading: (params) => params.senderName,
509
+ lines: (params) => [params.excerpt],
510
+ button: (ctx, params) => ({
511
+ href: chat(ctx, params.communityId, params.chatId),
512
+ label: "View request"
513
+ }),
514
+ preview: {
515
+ senderName: "Ann",
516
+ excerpt: "Hello",
517
+ chatId: "cht_1",
518
+ communityId: "cmy_1"
519
+ }
520
+ });
521
+ const newMessage = defineEmail({
522
+ subject: (_ctx, params) => `${params.senderName} in ${params.chatTitle}`,
523
+ heading: (params) => params.chatTitle,
524
+ lines: (params) => [`${params.senderName}: ${params.excerpt}`],
525
+ button: (ctx, params) => ({
526
+ href: chat(ctx, params.communityId, params.chatId),
527
+ label: "Open chat"
528
+ }),
529
+ preview: {
530
+ senderName: "Ann",
531
+ chatTitle: "Group chat",
532
+ excerpt: "Hello",
533
+ chatId: "cht_1",
534
+ communityId: "cmy_1"
535
+ }
536
+ });
537
+ const addedToGroupChat = defineEmail({
538
+ subject: (_ctx, params) => `${params.adderName} added you to a chat`,
539
+ heading: () => "You were added to a chat",
540
+ lines: (params) => [`${params.adderName} added you.`, params.participantNames.join(", ")],
541
+ button: (ctx, params) => ({
542
+ href: chat(ctx, params.communityId, params.chatId),
543
+ label: "Open chat"
544
+ }),
545
+ preview: {
546
+ adderName: "Ann",
547
+ participantNames: ["Ann", "Sam"],
548
+ chatId: "cht_1",
549
+ communityId: "cmy_1"
550
+ }
551
+ });
552
+ const ROLE_PATH = {
553
+ course: "courses",
554
+ download: "downloads",
555
+ community: "communities",
556
+ event: "events"
557
+ };
558
+ const roleAssigned = defineEmail({
559
+ subject: (_ctx, params) => `You are now ${params.roleName} ${params.place}`,
560
+ heading: (params) => `You are now ${params.roleName}`,
561
+ lines: (params) => [`You are now ${params.roleName} ${params.place}.`],
562
+ button: (ctx, params) => params.contentId !== null && params.contentType !== null ? {
563
+ href: `${ctx.baseUrl}/${ROLE_PATH[params.contentType] ?? ""}/${params.contentId}`,
564
+ label: "Open"
565
+ } : {
566
+ href: ctx.baseUrl,
567
+ label: "Open"
568
+ },
569
+ preview: {
570
+ roleName: "Moderator",
571
+ place: "of Founders",
572
+ contentId: "cmy_1",
573
+ contentType: "community"
574
+ }
575
+ });
576
+ function commentsLabel(count) {
577
+ return count === 1 ? "1 comment" : `${count} comments`;
578
+ }
579
+ function Digest({ ctx, params }) {
580
+ return /* @__PURE__ */ jsxs(Layout, {
581
+ ctx,
582
+ heading: `${params.communityTitle} digest`,
583
+ children: [
584
+ /* @__PURE__ */ jsx(Paragraph, { children: "Here's what you haven't seen." }),
585
+ params.posts.map((item) => /* @__PURE__ */ jsxs(Section, {
586
+ className: "my-[12px]",
587
+ children: [/* @__PURE__ */ jsx(Link, {
588
+ href: post(ctx, params.communityId, item.postId),
589
+ className: "text-[16px] font-semibold text-[#18181b]",
590
+ children: item.title
591
+ }), /* @__PURE__ */ jsx(Text, {
592
+ className: "my-[2px] text-[14px] leading-[1.4] text-[#6b7280]",
593
+ children: `${item.authorName} in ${item.spaceName} ยท ${commentsLabel(item.commentCount)}`
594
+ })]
595
+ }, item.postId)),
596
+ /* @__PURE__ */ jsx(EmailButton, {
597
+ href: community(ctx, params.communityId),
598
+ children: "Open community"
599
+ })
600
+ ]
601
+ });
602
+ }
603
+ Digest.PreviewProps = {
604
+ ctx: PREVIEW_CTX,
605
+ params: {
606
+ communityTitle: "Founders",
607
+ communityId: "cmy_1",
608
+ from: "2026-10-29T07:00:00.000Z",
609
+ to: "2026-11-05T07:00:00.000Z",
610
+ posts: [{
611
+ postId: "pst_1",
612
+ title: "Welcome, everyone",
613
+ authorName: "Sam",
614
+ spaceName: "Announcements",
615
+ commentCount: 4
616
+ }]
617
+ }
618
+ };
619
+ const digest = {
620
+ subject: (_ctx, params) => `${params.communityTitle} digest`,
621
+ Component: Digest
622
+ };
623
+ const postAwaitingReview = defineEmail({
624
+ subject: (_ctx, params) => `Post awaiting review in ${params.spaceName}`,
625
+ heading: (params) => params.postTitle,
626
+ lines: (params) => [`${params.authorName} submitted a post in ${params.spaceName}.`],
627
+ button: (ctx, params) => ({
628
+ href: space(ctx, params.communityId, params.spaceId),
629
+ label: "Review"
630
+ }),
631
+ preview: {
632
+ spaceName: "Announcements",
633
+ postTitle: "Hello",
634
+ authorName: "Sam",
635
+ spaceId: "spc_1",
636
+ communityId: "cmy_1"
637
+ }
638
+ });
639
+ const joinRequest = defineEmail({
640
+ subject: (_ctx, params) => `${params.memberName} requested ${params.spaceName}`,
641
+ heading: (params) => params.spaceName,
642
+ lines: (params) => [`${params.memberName} asked to join. Seats left: ${params.seatsLeft}.`],
643
+ button: (ctx, params) => ({
644
+ href: space(ctx, params.communityId, params.spaceId),
645
+ label: "Review request"
646
+ }),
647
+ preview: {
648
+ spaceName: "SaaS",
649
+ memberName: "Sam",
650
+ seatsLeft: "3",
651
+ spaceId: "spc_1",
652
+ communityId: "cmy_1"
653
+ }
654
+ });
655
+ const somethingWasFlagged = defineEmail({
656
+ subject: (_ctx, params) => `Something was flagged in ${params.spaceName}`,
657
+ heading: (params) => params.spaceName,
658
+ lines: (params) => [params.reason, params.excerpt],
659
+ button: (ctx, params) => ({
660
+ href: space(ctx, params.communityId, params.spaceId),
661
+ label: "Review"
662
+ }),
663
+ preview: {
664
+ spaceName: "Announcements",
665
+ excerpt: "Hello",
666
+ reason: "Spam",
667
+ spaceId: "spc_1",
668
+ communityId: "cmy_1"
669
+ }
670
+ });
671
+ const messageWasFlagged = defineEmail({
672
+ subject: () => "A message was flagged",
673
+ heading: () => "A message was flagged",
674
+ lines: (params) => [params.reason],
675
+ button: (ctx, params) => ({
676
+ href: community(ctx, params.communityId),
677
+ label: "Review"
678
+ }),
679
+ preview: {
680
+ reason: "Spam",
681
+ communityId: "cmy_1"
682
+ }
683
+ });
684
+ const postReacted = defineEmail({
685
+ subject: (_ctx, params) => `${params.reactorName} reacted to your post`,
686
+ heading: (params) => params.postTitle,
687
+ lines: (params) => [`${params.reactorName} reacted ${params.reaction} to your post.`],
688
+ button: (ctx, params) => ({
689
+ href: post(ctx, params.communityId, params.postId),
690
+ label: "View post"
691
+ }),
692
+ preview: {
693
+ postTitle: "Hello",
694
+ reactorName: "Sam",
695
+ reaction: "๐Ÿ‘",
696
+ postId: "pst_1",
697
+ communityId: "cmy_1"
698
+ }
699
+ });
700
+ const commentReacted = defineEmail({
701
+ subject: (_ctx, params) => `${params.reactorName} reacted to your comment`,
702
+ heading: (params) => params.postTitle,
703
+ lines: (params) => [`${params.reactorName} reacted ${params.reaction} to:`, params.excerpt],
704
+ button: (ctx, params) => ({
705
+ href: comment(ctx, params.communityId, params.postId, params.commentId),
706
+ label: "View comment"
707
+ }),
708
+ preview: {
709
+ postTitle: "Hello",
710
+ excerpt: "Nice",
711
+ reactorName: "Sam",
712
+ reaction: "๐Ÿ‘",
713
+ commentId: "cmt_1",
714
+ postId: "pst_1",
715
+ communityId: "cmy_1"
716
+ }
717
+ });
718
+ function mentionedIn(params) {
719
+ return "postTitle" in params ? params.postTitle : params.chatTitle;
720
+ }
721
+ const mention = defineEmail({
722
+ subject: (_ctx, params) => `${params.authorName} mentioned you in ${mentionedIn(params)}`,
723
+ heading: (params) => mentionedIn(params),
724
+ lines: (params) => [params.authorName, params.excerpt],
725
+ button: (ctx, params) => "postTitle" in params ? {
726
+ href: params.commentId ? comment(ctx, params.communityId, params.postId, params.commentId) : post(ctx, params.communityId, params.postId),
727
+ label: "View"
728
+ } : {
729
+ href: chat(ctx, params.communityId, params.chatId),
730
+ label: "Open chat"
731
+ },
732
+ preview: {
733
+ authorName: "Sam",
734
+ excerpt: "Thanks @Ann",
735
+ communityId: "cmy_1",
736
+ postTitle: "Hello",
737
+ postId: "pst_1",
738
+ commentId: "cmt_1"
739
+ }
740
+ });
741
+ const messageReacted = defineEmail({
742
+ subject: (_ctx, params) => `${params.reactorName} reacted to your message`,
743
+ heading: () => "A reaction to your message",
744
+ lines: (params) => [`${params.reactorName} reacted ${params.reaction} to:`, params.excerpt],
745
+ button: (ctx, params) => ({
746
+ href: chat(ctx, params.communityId, params.chatId),
747
+ label: "Open chat"
748
+ }),
749
+ preview: {
750
+ excerpt: "Hello",
751
+ reactorName: "Sam",
752
+ reaction: "๐Ÿ‘",
753
+ chatId: "cht_1",
754
+ communityId: "cmy_1"
755
+ }
756
+ });
757
+ //#endregion
758
+ //#region src/emails/course-activity.tsx
759
+ const activity = (ctx, courseId, activityId) => portal(ctx, `/courses/${courseId}?activity=${activityId}`);
760
+ const courseActivityAdded = defineEmail({
761
+ subject: (_ctx, params) => `New in ${params.courseTitle}: ${params.activityTitle}`,
762
+ heading: (params) => params.activityTitle,
763
+ lines: (params) => [`${params.courseTitle}, ${params.moduleTitle}`],
764
+ button: (ctx, params) => ({
765
+ href: activity(ctx, params.courseId, params.activityId),
766
+ label: "Open lesson"
767
+ }),
768
+ preview: {
769
+ courseTitle: "Fly Tying 101",
770
+ moduleTitle: "Basics",
771
+ activityTitle: "Choosing hooks",
772
+ courseId: "crs_1",
773
+ activityId: "act_1"
774
+ }
775
+ });
776
+ const activityCommentCreated = defineEmail({
777
+ subject: (_ctx, params) => `${params.commenterName} commented on ${params.activityTitle}`,
778
+ heading: (params) => params.activityTitle,
779
+ lines: (params) => [
780
+ params.courseTitle,
781
+ params.commenterName,
782
+ params.excerpt
783
+ ],
784
+ button: (ctx, params) => ({
785
+ href: activity(ctx, params.courseId, params.activityId),
786
+ label: "View comment"
787
+ }),
788
+ preview: {
789
+ activityTitle: "Choosing hooks",
790
+ courseTitle: "Fly Tying 101",
791
+ commenterName: "Sam",
792
+ excerpt: "Nice",
793
+ courseId: "crs_1",
794
+ activityId: "act_1",
795
+ commentId: "cmt_1"
796
+ }
797
+ });
798
+ const activityCommentRemoved = defineEmail({
799
+ subject: (_ctx, params) => `Your comment was removed from ${params.activityTitle}`,
800
+ heading: (params) => params.activityTitle,
801
+ lines: (params) => [`Your comment in ${params.courseTitle} was removed.`],
802
+ button: (ctx, params) => ({
803
+ href: activity(ctx, params.courseId, params.activityId),
804
+ label: "Open lesson"
805
+ }),
806
+ preview: {
807
+ activityTitle: "Choosing hooks",
808
+ courseTitle: "Fly Tying 101",
809
+ courseId: "crs_1",
810
+ activityId: "act_1"
811
+ }
812
+ });
813
+ const activityCommentReacted = defineEmail({
814
+ subject: (_ctx, params) => `${params.reactorName} reacted to your comment`,
815
+ heading: (params) => params.activityTitle,
816
+ lines: (params) => [`${params.reactorName} reacted ${params.reaction} to:`, params.excerpt],
817
+ button: (ctx, params) => ({
818
+ href: activity(ctx, params.courseId, params.activityId),
819
+ label: "View comment"
820
+ }),
821
+ preview: {
822
+ activityTitle: "Choosing hooks",
823
+ courseTitle: "Fly Tying 101",
824
+ excerpt: "Nice",
825
+ reactorName: "Sam",
826
+ reaction: "๐Ÿ‘",
827
+ courseId: "crs_1",
828
+ activityId: "act_1",
829
+ commentId: "cmt_1"
830
+ }
831
+ });
832
+ const activityCommentFlagged = defineEmail({
833
+ subject: (_ctx, params) => `A comment was flagged in ${params.activityTitle}`,
834
+ heading: (params) => params.activityTitle,
835
+ lines: (params) => [
836
+ params.courseTitle,
837
+ params.reason,
838
+ params.excerpt
839
+ ],
840
+ button: (ctx, params) => ({
841
+ href: activity(ctx, params.courseId, params.activityId),
842
+ label: "Review"
843
+ }),
844
+ preview: {
845
+ activityTitle: "Choosing hooks",
846
+ courseTitle: "Fly Tying 101",
847
+ excerpt: "Hello",
848
+ reason: "Spam",
849
+ courseId: "crs_1",
850
+ activityId: "act_1"
851
+ }
852
+ });
853
+ const activityMention = defineEmail({
854
+ subject: (_ctx, params) => `${params.authorName} mentioned you in ${params.activityTitle}`,
855
+ heading: (params) => params.activityTitle,
856
+ lines: (params) => [
857
+ params.courseTitle,
858
+ params.authorName,
859
+ params.excerpt
860
+ ],
861
+ button: (ctx, params) => ({
862
+ href: activity(ctx, params.courseId, params.activityId),
863
+ label: "View"
864
+ }),
865
+ preview: {
866
+ authorName: "Sam",
867
+ excerpt: "Thanks @Ann",
868
+ activityTitle: "Choosing hooks",
869
+ courseTitle: "Fly Tying 101",
870
+ courseId: "crs_1",
871
+ activityId: "act_1"
872
+ }
873
+ });
874
+ //#endregion
875
+ //#region src/emails/events.tsx
876
+ const PREVIEW_EVENT = {
877
+ eventId: "evn_1",
878
+ eventTitle: "Conversation practice",
879
+ startsAt: "2026-05-12T16:00:00.000Z",
880
+ endsAt: "2026-05-12T17:00:00.000Z",
881
+ timeZone: "Europe/London"
882
+ };
883
+ function eventPage(ctx, eventId) {
884
+ return portal(ctx, `/events/${eventId}`);
885
+ }
886
+ function formatIn(value, timeZone, options) {
887
+ const date = new Date(value);
888
+ if (Number.isNaN(date.getTime())) return value;
889
+ try {
890
+ return new Intl.DateTimeFormat("en-US", {
891
+ ...options,
892
+ timeZone
893
+ }).format(date);
894
+ } catch {
895
+ return new Intl.DateTimeFormat("en-US", {
896
+ ...options,
897
+ timeZone: "UTC"
898
+ }).format(date);
899
+ }
900
+ }
901
+ function eventWhen(params) {
902
+ const day = formatIn(params.startsAt, params.timeZone, {
903
+ weekday: "long",
904
+ day: "numeric",
905
+ month: "long",
906
+ year: "numeric"
907
+ });
908
+ const time = {
909
+ hour: "numeric",
910
+ minute: "2-digit"
911
+ };
912
+ return `${day}, ${formatIn(params.startsAt, params.timeZone, time)} โ€“ ${formatIn(params.endsAt, params.timeZone, time)} (${params.timeZone})`;
913
+ }
914
+ function calendarStamp(value) {
915
+ return new Date(value).toISOString().replace(/[-:]/g, "").replace(/\.\d{3}/, "");
916
+ }
917
+ function googleCalendarUrl(ctx, params) {
918
+ return `https://calendar.google.com/calendar/render?${new URLSearchParams({
919
+ action: "TEMPLATE",
920
+ text: params.eventTitle,
921
+ dates: `${calendarStamp(params.startsAt)}/${calendarStamp(params.endsAt)}`,
922
+ details: eventPage(ctx, params.eventId),
923
+ ctz: params.timeZone
924
+ }).toString()}`;
925
+ }
926
+ function outlookCalendarUrl(ctx, params) {
927
+ return `https://outlook.live.com/calendar/0/action/compose?${new URLSearchParams({
928
+ path: "/calendar/action/compose",
929
+ rru: "addevent",
930
+ subject: params.eventTitle,
931
+ startdt: new Date(params.startsAt).toISOString(),
932
+ enddt: new Date(params.endsAt).toISOString(),
933
+ body: eventPage(ctx, params.eventId)
934
+ }).toString()}`;
935
+ }
936
+ function EventGranted({ ctx, params }) {
937
+ return /* @__PURE__ */ jsxs(Layout, {
938
+ ctx,
939
+ heading: `You're going to ${params.eventTitle}`,
940
+ children: [
941
+ /* @__PURE__ */ jsx(Paragraph, { children: eventWhen(params) }),
942
+ /* @__PURE__ */ jsx(EmailButton, {
943
+ href: eventPage(ctx, params.eventId),
944
+ children: "Open event"
945
+ }),
946
+ /* @__PURE__ */ jsx(Section, { children: /* @__PURE__ */ jsxs(Paragraph, { children: [
947
+ /* @__PURE__ */ jsx(Link, {
948
+ href: googleCalendarUrl(ctx, params),
949
+ children: "Add to Google Calendar"
950
+ }),
951
+ " ยท ",
952
+ /* @__PURE__ */ jsx(Link, {
953
+ href: outlookCalendarUrl(ctx, params),
954
+ children: "Add to Outlook"
955
+ })
956
+ ] }) })
957
+ ]
958
+ });
959
+ }
960
+ EventGranted.PreviewProps = {
961
+ ctx: PREVIEW_CTX,
962
+ params: PREVIEW_EVENT
963
+ };
964
+ const eventGranted = {
965
+ subject: (_ctx, params) => `You're going to ${params.eventTitle}`,
966
+ Component: EventGranted
967
+ };
968
+ const CHANGED = {
969
+ time: "The time has changed.",
970
+ location: "The location has changed. Open the event for the new details.",
971
+ time_and_location: "The time and the location have changed. Open the event for the new details."
972
+ };
973
+ const open = (ctx, params) => ({
974
+ href: eventPage(ctx, params.eventId),
975
+ label: "Open event"
976
+ });
977
+ const eventStartingSoon = defineEmail({
978
+ subject: (_ctx, params) => `${params.eventTitle} starts in ${params.leadText}`,
979
+ heading: (params) => `${params.eventTitle} starts in ${params.leadText}`,
980
+ lines: (params) => [eventWhen(params), "Open the event for the link."],
981
+ button: open,
982
+ preview: {
983
+ ...PREVIEW_EVENT,
984
+ leadText: "1 hour"
985
+ }
986
+ });
987
+ const eventChanged = defineEmail({
988
+ subject: (_ctx, params) => `${params.eventTitle} has changed`,
989
+ heading: (params) => `${params.eventTitle} has changed`,
990
+ lines: (params) => [CHANGED[params.changed], eventWhen(params)],
991
+ button: open,
992
+ preview: {
993
+ ...PREVIEW_EVENT,
994
+ changed: "time"
995
+ }
996
+ });
997
+ const eventCanceled = defineEmail({
998
+ subject: (_ctx, params) => `${params.eventTitle} was canceled`,
999
+ heading: (params) => `${params.eventTitle} was canceled`,
1000
+ lines: (params) => [`It was planned for ${eventWhen(params)}.`],
1001
+ button: open,
1002
+ preview: PREVIEW_EVENT
1003
+ });
1004
+ const eventRevoked = defineEmail({
1005
+ subject: (_ctx, params) => `You're no longer going to ${params.eventTitle}`,
1006
+ heading: (params) => `You're no longer going to ${params.eventTitle}`,
1007
+ lines: (params) => [`You've been removed from the event on ${eventWhen(params)}.`],
1008
+ button: open,
1009
+ preview: PREVIEW_EVENT
1010
+ });
1011
+ //#endregion
233
1012
  //#region src/index.tsx
234
1013
  const registry = {
235
1014
  magicLink: {
236
- subject: subject$7,
1015
+ subject: subject$8,
237
1016
  Component: MagicLink
238
1017
  },
239
1018
  studentInvite: {
240
- subject: subject$6,
1019
+ subject: subject$7,
241
1020
  Component: StudentInvite
242
1021
  },
243
1022
  memberInvite: {
244
- subject: subject$5,
1023
+ subject: subject$6,
245
1024
  Component: MemberInvite
246
1025
  },
247
1026
  passwordReset: {
248
- subject: subject$4,
1027
+ subject: subject$5,
249
1028
  Component: PasswordReset
250
1029
  },
1030
+ passwordChanged: {
1031
+ subject: subject$4,
1032
+ Component: PasswordChanged
1033
+ },
251
1034
  emailVerification: {
252
1035
  subject: subject$3,
253
1036
  Component: EmailVerification
@@ -263,6 +1046,150 @@ const registry = {
263
1046
  courseCompleted: {
264
1047
  subject,
265
1048
  Component: CourseCompleted
1049
+ },
1050
+ welcomeToCommunity: {
1051
+ subject: welcomeToCommunity.subject,
1052
+ Component: welcomeToCommunity.Component
1053
+ },
1054
+ membershipEndingSoon: {
1055
+ subject: membershipEndingSoon.subject,
1056
+ Component: membershipEndingSoon.Component
1057
+ },
1058
+ membershipEnded: {
1059
+ subject: membershipEnded.subject,
1060
+ Component: membershipEnded.Component
1061
+ },
1062
+ newPostInSpace: {
1063
+ subject: newPostInSpace.subject,
1064
+ Component: newPostInSpace.Component
1065
+ },
1066
+ yourPostWasPublished: {
1067
+ subject: yourPostWasPublished.subject,
1068
+ Component: yourPostWasPublished.Component
1069
+ },
1070
+ yourPostWasRemoved: {
1071
+ subject: yourPostWasRemoved.subject,
1072
+ Component: yourPostWasRemoved.Component
1073
+ },
1074
+ newCommentOnPost: {
1075
+ subject: newCommentOnPost.subject,
1076
+ Component: newCommentOnPost.Component
1077
+ },
1078
+ replyToYourComment: {
1079
+ subject: replyToYourComment.subject,
1080
+ Component: replyToYourComment.Component
1081
+ },
1082
+ yourCommentWasRemoved: {
1083
+ subject: yourCommentWasRemoved.subject,
1084
+ Component: yourCommentWasRemoved.Component
1085
+ },
1086
+ requestApproved: {
1087
+ subject: requestApproved.subject,
1088
+ Component: requestApproved.Component
1089
+ },
1090
+ requestDeclined: {
1091
+ subject: requestDeclined.subject,
1092
+ Component: requestDeclined.Component
1093
+ },
1094
+ invitedToSpace: {
1095
+ subject: invitedToSpace.subject,
1096
+ Component: invitedToSpace.Component
1097
+ },
1098
+ messageRequest: {
1099
+ subject: messageRequest.subject,
1100
+ Component: messageRequest.Component
1101
+ },
1102
+ newMessage: {
1103
+ subject: newMessage.subject,
1104
+ Component: newMessage.Component
1105
+ },
1106
+ addedToGroupChat: {
1107
+ subject: addedToGroupChat.subject,
1108
+ Component: addedToGroupChat.Component
1109
+ },
1110
+ roleAssigned: {
1111
+ subject: roleAssigned.subject,
1112
+ Component: roleAssigned.Component
1113
+ },
1114
+ digest: {
1115
+ subject: digest.subject,
1116
+ Component: digest.Component
1117
+ },
1118
+ postAwaitingReview: {
1119
+ subject: postAwaitingReview.subject,
1120
+ Component: postAwaitingReview.Component
1121
+ },
1122
+ joinRequest: {
1123
+ subject: joinRequest.subject,
1124
+ Component: joinRequest.Component
1125
+ },
1126
+ somethingWasFlagged: {
1127
+ subject: somethingWasFlagged.subject,
1128
+ Component: somethingWasFlagged.Component
1129
+ },
1130
+ messageWasFlagged: {
1131
+ subject: messageWasFlagged.subject,
1132
+ Component: messageWasFlagged.Component
1133
+ },
1134
+ postReacted: {
1135
+ subject: postReacted.subject,
1136
+ Component: postReacted.Component
1137
+ },
1138
+ commentReacted: {
1139
+ subject: commentReacted.subject,
1140
+ Component: commentReacted.Component
1141
+ },
1142
+ mention: {
1143
+ subject: mention.subject,
1144
+ Component: mention.Component
1145
+ },
1146
+ messageReacted: {
1147
+ subject: messageReacted.subject,
1148
+ Component: messageReacted.Component
1149
+ },
1150
+ courseActivityAdded: {
1151
+ subject: courseActivityAdded.subject,
1152
+ Component: courseActivityAdded.Component
1153
+ },
1154
+ activityCommentCreated: {
1155
+ subject: activityCommentCreated.subject,
1156
+ Component: activityCommentCreated.Component
1157
+ },
1158
+ activityCommentRemoved: {
1159
+ subject: activityCommentRemoved.subject,
1160
+ Component: activityCommentRemoved.Component
1161
+ },
1162
+ activityCommentReacted: {
1163
+ subject: activityCommentReacted.subject,
1164
+ Component: activityCommentReacted.Component
1165
+ },
1166
+ activityCommentFlagged: {
1167
+ subject: activityCommentFlagged.subject,
1168
+ Component: activityCommentFlagged.Component
1169
+ },
1170
+ activityMention: {
1171
+ subject: activityMention.subject,
1172
+ Component: activityMention.Component
1173
+ },
1174
+ eventGranted: {
1175
+ subject: eventGranted.subject,
1176
+ Component: eventGranted.Component
1177
+ },
1178
+ eventStartingSoon: {
1179
+ subject: eventStartingSoon.subject,
1180
+ Component: eventStartingSoon.Component
1181
+ },
1182
+ eventChanged: {
1183
+ subject: eventChanged.subject,
1184
+ Component: eventChanged.Component
1185
+ },
1186
+ eventCanceled: {
1187
+ subject: eventCanceled.subject,
1188
+ Component: eventCanceled.Component
1189
+ },
1190
+ eventRevoked: {
1191
+ subject: eventRevoked.subject,
1192
+ Component: eventRevoked.Component
266
1193
  }
267
1194
  };
268
1195
  var ReactEmailTemplateRenderer = class {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["subject","subject","subject","subject","subject","subject","subject","magicLink","studentInvite","memberInvite","passwordReset","emailVerification","accessGranted","accessRevoked","courseCompleted"],"sources":["../src/emails/layout.tsx","../src/emails/magic-link.tsx","../src/emails/student-invite.tsx","../src/emails/member-invite.tsx","../src/emails/password-reset.tsx","../src/emails/email-verification.tsx","../src/emails/access-granted.tsx","../src/emails/access-revoked.tsx","../src/emails/course-completed.tsx","../src/index.tsx"],"sourcesContent":["import { Body, Button, Container, Head, Heading, Hr, Html, Img, Link, Section, Tailwind, Text } from '@react-email/components';\nimport type { ReactNode } from 'react';\nimport type { TemplateContext } from '@headless-lms/core/types';\n\nexport function Layout({ ctx, heading, children }: {\n ctx: TemplateContext;\n heading: string;\n children: ReactNode;\n}) {\n return (\n <Html>\n <Tailwind>\n <Head />\n <Body className=\"bg-white font-sans\">\n <Container className=\"mx-auto max-w-[560px] px-6 pt-5 pb-12\">\n {ctx.logoUrl ? (\n <Img src={ctx.logoUrl} alt={ctx.brandName} height={42} className=\"h-[42px]\" />\n ) : (\n <Text className=\"m-0 text-[15px] font-semibold text-[#3c4149]\">{ctx.brandName}</Text>\n )}\n <Heading className=\"mt-[28px] mb-0 text-[24px] font-normal leading-[1.3] tracking-[-0.5px] text-[#484848]\">\n {heading}\n </Heading>\n <Section>{children}</Section>\n <Hr className=\"mt-[42px] mb-[26px] border-[#dfe1e4]\" />\n <Link href={ctx.baseUrl} className=\"text-[14px] text-[#b4becc]\">\n {ctx.brandName}\n </Link>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n}\n\nexport function EmailButton({ href, children }: { href: string; children: ReactNode }) {\n return (\n <Section className=\"py-[20px]\">\n <Button\n href={href}\n className=\"rounded-[3px] bg-[#18181b] px-[23px] py-[11px] text-[15px] font-semibold text-white no-underline\"\n >\n {children}\n </Button>\n </Section>\n );\n}\n\nexport function Paragraph({ children }: { children: ReactNode }) {\n return <Text className=\"my-[15px] text-[15px] leading-[1.4] text-[#3c4149]\">{children}</Text>;\n}\n\nexport const PREVIEW_CTX: TemplateContext = {\n brandName: 'Acme LMS',\n baseUrl: 'http://localhost:8001',\n studentPortalUrl: 'http://localhost:8002',\n};\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['magicLink'];\n\nexport const subject = (ctx: TemplateContext, _params: Params) => `Sign in to ${ctx.brandName}`;\n\nexport default function MagicLink({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Sign in\">\n <Paragraph>Click the button below to sign in. This link is valid once and expires shortly.</Paragraph>\n <EmailButton href={params.url}>Sign in to {ctx.brandName}</EmailButton>\n <Paragraph>If you did not request this, you can ignore this email.</Paragraph>\n </Layout>\n );\n}\n\nMagicLink.PreviewProps = { ctx: PREVIEW_CTX, params: { url: 'http://localhost:8002/magic?token=demo' } };\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['studentInvite'];\n\nexport const subject = (ctx: TemplateContext, _params: Params) => `You're invited to ${ctx.brandName}`;\n\nexport default function StudentInvite({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Welcome\">\n <Paragraph>\n {params.studentName}, you've been invited to {ctx.brandName}. Create your account to get started.\n </Paragraph>\n <EmailButton href={params.inviteUrl}>Create your account</EmailButton>\n <Paragraph>This invitation link is personal โ€” please don't forward it.</Paragraph>\n </Layout>\n );\n}\n\nStudentInvite.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n inviteUrl: 'http://localhost:8002/welcome?token=demo',\n studentName: 'Sam',\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['memberInvite'];\n\nexport const subject = (ctx: TemplateContext, _params: Params) =>\n `You've been invited to join ${ctx.brandName}`;\n\nexport default function MemberInvite({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading={`Join ${ctx.brandName}`}>\n <Paragraph>\n {params.inviterName} invited you to join {ctx.brandName} as {params.role}.\n </Paragraph>\n <EmailButton href={params.inviteUrl}>Accept invitation</EmailButton>\n <Paragraph>If you weren't expecting this invitation, you can ignore this email.</Paragraph>\n </Layout>\n );\n}\n\nMemberInvite.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n inviteUrl: 'http://localhost:8001/invite?token=demo',\n inviterName: 'Ann',\n role: 'admin',\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['passwordReset'];\n\nexport const subject = (ctx: TemplateContext, _params: Params) => `Reset your ${ctx.brandName} password`;\n\nexport default function PasswordReset({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Reset your password\">\n <Paragraph>Click the button below to choose a new password. The link expires shortly.</Paragraph>\n <EmailButton href={params.resetUrl}>Reset password</EmailButton>\n <Paragraph>If you did not request a reset, your password is unchanged and you can ignore this email.</Paragraph>\n </Layout>\n );\n}\n\nPasswordReset.PreviewProps = { ctx: PREVIEW_CTX, params: { resetUrl: 'http://localhost:8002/reset?token=demo' } };\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['emailVerification'];\n\nexport const subject = (ctx: TemplateContext, _params: Params) => `Verify your email for ${ctx.brandName}`;\n\nexport default function EmailVerification({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Verify your email\">\n <Paragraph>Confirm this is your email address to finish setting up your account.</Paragraph>\n <EmailButton href={params.verifyUrl}>Verify email</EmailButton>\n </Layout>\n );\n}\n\nEmailVerification.PreviewProps = { ctx: PREVIEW_CTX, params: { verifyUrl: 'http://localhost:8002/verify?token=demo' } };\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['accessGranted'];\n\nexport const subject = (_ctx: TemplateContext, params: Params) =>\n `You now have access to ${params.contentTitle}`;\n\nexport default function AccessGranted({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading={`${params.contentTitle} is ready for you`}>\n <Paragraph>You've been granted access. Jump in whenever you're ready.</Paragraph>\n <EmailButton href={`${ctx.studentPortalUrl}/courses/${params.contentId}`}>Start learning</EmailButton>\n </Layout>\n );\n}\n\nAccessGranted.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n contentTitle: 'Fly Tying 101',\n contentId: 'demo',\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['accessRevoked'];\n\nexport const subject = (_ctx: TemplateContext, params: Params) =>\n `Your access to ${params.contentTitle} has ended`;\n\nexport default function AccessRevoked({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Access ended\">\n <Paragraph>\n Your access to {params.contentTitle} has ended. If you think this is a mistake, reply to this email.\n </Paragraph>\n </Layout>\n );\n}\n\nAccessRevoked.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n contentTitle: 'Fly Tying 101',\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from '@headless-lms/core/types';\nimport { Layout, Paragraph, PREVIEW_CTX } from './layout.js';\n\ntype Params = EmailTemplateParams['courseCompleted'];\n\nexport const subject = (_ctx: TemplateContext, params: Params) => `You completed ${params.courseTitle} ๐ŸŽ‰`;\n\nexport default function CourseCompleted({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Congratulations!\">\n <Paragraph>You've completed {params.courseTitle}. Nice work.</Paragraph>\n </Layout>\n );\n}\n\nCourseCompleted.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n courseTitle: 'Fly Tying 101',\n },\n};\n","// Default TemplateRenderer: react-email components rendered at call time.\nimport { render } from '@react-email/render';\nimport type { JSX } from 'react';\nimport type {\n EmailContent,\n EmailTemplateId,\n EmailTemplateParams,\n TemplateContext,\n TemplateRenderer,\n} from '@headless-lms/core/types';\nimport MagicLink, { subject as magicLink } from './emails/magic-link.js';\nimport StudentInvite, { subject as studentInvite } from './emails/student-invite.js';\nimport MemberInvite, { subject as memberInvite } from './emails/member-invite.js';\nimport PasswordReset, { subject as passwordReset } from './emails/password-reset.js';\nimport EmailVerification, { subject as emailVerification } from './emails/email-verification.js';\nimport AccessGranted, { subject as accessGranted } from './emails/access-granted.js';\nimport AccessRevoked, { subject as accessRevoked } from './emails/access-revoked.js';\nimport CourseCompleted, { subject as courseCompleted } from './emails/course-completed.js';\n\ninterface Entry<K extends EmailTemplateId> {\n subject: (ctx: TemplateContext, params: EmailTemplateParams[K]) => string;\n Component: (props: { ctx: TemplateContext; params: EmailTemplateParams[K] }) => JSX.Element;\n}\n\n// The catalog is closed: a missing key here is a compile error.\nconst registry: { [K in EmailTemplateId]: Entry<K> } = {\n magicLink: { subject: magicLink, Component: MagicLink },\n studentInvite: { subject: studentInvite, Component: StudentInvite },\n memberInvite: { subject: memberInvite, Component: MemberInvite },\n passwordReset: { subject: passwordReset, Component: PasswordReset },\n emailVerification: { subject: emailVerification, Component: EmailVerification },\n accessGranted: { subject: accessGranted, Component: AccessGranted },\n accessRevoked: { subject: accessRevoked, Component: AccessRevoked },\n courseCompleted: { subject: courseCompleted, Component: CourseCompleted },\n};\n\nexport class ReactEmailTemplateRenderer implements TemplateRenderer {\n async render<K extends EmailTemplateId>(\n id: K,\n ctx: TemplateContext,\n params: EmailTemplateParams[K],\n ): Promise<EmailContent> {\n const entry = registry[id] as Entry<K>;\n const element = <entry.Component ctx={ctx} params={params} />;\n const [html, text] = await Promise.all([render(element), render(element, { plainText: true })]);\n return { subject: entry.subject(ctx, params), html, text };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["subject","subject","subject","subject","subject","subject","subject","subject","magicLink","studentInvite","memberInvite","passwordReset","passwordChanged","emailVerification","accessGranted","accessRevoked","courseCompleted"],"sources":["../src/emails/layout.tsx","../src/emails/magic-link.tsx","../src/emails/student-invite.tsx","../src/emails/member-invite.tsx","../src/emails/password-reset.tsx","../src/emails/password-changed.tsx","../src/emails/email-verification.tsx","../src/emails/access-granted.tsx","../src/emails/access-revoked.tsx","../src/emails/course-completed.tsx","../src/emails/community.tsx","../src/emails/course-activity.tsx","../src/emails/events.tsx","../src/index.tsx"],"sourcesContent":["import {\n Body,\n Button,\n Column,\n Container,\n Head,\n Heading,\n Hr,\n Html,\n Img,\n Link,\n Row,\n Section,\n Tailwind,\n Text,\n} from \"@react-email/components\";\nimport type { ReactNode } from \"react\";\nimport type { TemplateContext } from \"@headless-lms/core/types\";\n\nconst LOGO_URL = \"https://headless-lms.dev/logo.png\";\nconst ICON_URL = \"https://headless-lms.dev/apple-icon\";\n\nexport function Layout({\n ctx,\n heading,\n children,\n}: {\n ctx: TemplateContext;\n heading: string;\n children: ReactNode;\n}) {\n return (\n <Html>\n <Tailwind>\n <Head />\n <Body className=\"bg-white font-sans\">\n <Container className=\"mx-auto max-w-[560px] px-6 pt-5 pb-12\">\n <Img src={LOGO_URL} alt={ctx.brandName} height={32} className=\"h-[32px]\" />\n <Heading className=\"mt-[28px] mb-0 text-[24px] font-normal leading-[1.3] tracking-[-0.5px] text-[#484848]\">\n {heading}\n </Heading>\n <Section>{children}</Section>\n <Hr className=\"mt-[42px] mb-[26px] border-[#dfe1e4]\" />\n <Row>\n <Column className=\"w-[24px]\">\n <Img src={ICON_URL} alt=\"\" width={24} height={24} className=\"rounded-[6px]\" />\n </Column>\n <Column className=\"pl-[8px]\">\n <Link href={ctx.baseUrl} className=\"text-[14px] text-[#b4becc]\">\n {ctx.brandName}\n </Link>\n </Column>\n </Row>\n </Container>\n </Body>\n </Tailwind>\n </Html>\n );\n}\n\nexport function EmailButton({ href, children }: { href: string; children: ReactNode }) {\n return (\n <Section className=\"py-[20px]\">\n <Button\n href={href}\n className=\"rounded-[3px] bg-[#18181b] px-[23px] py-[11px] text-[15px] font-semibold text-white no-underline\"\n >\n {children}\n </Button>\n </Section>\n );\n}\n\nexport function Paragraph({ children }: { children: ReactNode }) {\n return <Text className=\"my-[15px] text-[15px] leading-[1.4] text-[#3c4149]\">{children}</Text>;\n}\n\nexport const PREVIEW_CTX: TemplateContext = {\n brandName: \"Acme LMS\",\n baseUrl: \"http://localhost:8001\",\n studentPortalUrl: \"http://localhost:8002\",\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"magicLink\"];\n\nexport const subject = (ctx: TemplateContext, _params: Params) => `Sign in to ${ctx.brandName}`;\n\nexport default function MagicLink({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Sign in\">\n <Paragraph>\n Click the button below to sign in. This link is valid once and expires shortly.\n </Paragraph>\n <EmailButton href={params.url}>Sign in to {ctx.brandName}</EmailButton>\n <Paragraph>If you did not request this, you can ignore this email.</Paragraph>\n </Layout>\n );\n}\n\nMagicLink.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: { url: \"http://localhost:8002/magic?token=demo\" },\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"studentInvite\"];\n\nexport const subject = (ctx: TemplateContext, _params: Params) =>\n `You're invited to ${ctx.brandName}`;\n\nexport default function StudentInvite({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Welcome\">\n <Paragraph>\n {params.studentName}, you've been invited to {ctx.brandName}. Create your account to get\n started.\n </Paragraph>\n <EmailButton href={params.inviteUrl}>Create your account</EmailButton>\n <Paragraph>This invitation link is personal โ€” please don't forward it.</Paragraph>\n </Layout>\n );\n}\n\nStudentInvite.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n inviteUrl: \"http://localhost:8002/welcome?token=demo\",\n studentName: \"Sam\",\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"memberInvite\"];\n\nexport const subject = (ctx: TemplateContext, _params: Params) =>\n `You've been invited to join ${ctx.brandName}`;\n\nexport default function MemberInvite({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading={`Join ${ctx.brandName}`}>\n <Paragraph>\n {params.inviterName} invited you to join {ctx.brandName} as {params.role}.\n </Paragraph>\n <EmailButton href={params.inviteUrl}>Accept invitation</EmailButton>\n <Paragraph>If you weren't expecting this invitation, you can ignore this email.</Paragraph>\n </Layout>\n );\n}\n\nMemberInvite.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n inviteUrl: \"http://localhost:8001/invite?token=demo\",\n inviterName: \"Ann\",\n role: \"Admin\",\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"passwordReset\"];\n\nexport const subject = (ctx: TemplateContext, _params: Params) =>\n `Reset your ${ctx.brandName} password`;\n\nexport default function PasswordReset({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Reset your password\">\n <Paragraph>\n Click the button below to choose a new password. The link expires shortly.\n </Paragraph>\n <EmailButton href={params.resetUrl}>Reset password</EmailButton>\n <Paragraph>\n If you did not request a reset, your password is unchanged and you can ignore this email.\n </Paragraph>\n </Layout>\n );\n}\n\nPasswordReset.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: { resetUrl: \"http://localhost:8002/reset?token=demo\" },\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"passwordChanged\"];\n\nexport const subject = (ctx: TemplateContext, _params: Params) =>\n `Your ${ctx.brandName} password was changed`;\n\nexport default function PasswordChanged({ ctx }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Your password was changed\">\n <Paragraph>The password for your {ctx.brandName} account was just changed.</Paragraph>\n <Paragraph>If you didn't make this change, reply to this email right away.</Paragraph>\n </Layout>\n );\n}\n\nPasswordChanged.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {},\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"emailVerification\"];\n\nexport const subject = (ctx: TemplateContext, _params: Params) =>\n `Verify your email for ${ctx.brandName}`;\n\nexport default function EmailVerification({\n ctx,\n params,\n}: {\n ctx: TemplateContext;\n params: Params;\n}) {\n return (\n <Layout ctx={ctx} heading=\"Verify your email\">\n <Paragraph>Confirm this is your email address to finish setting up your account.</Paragraph>\n <EmailButton href={params.verifyUrl}>Verify email</EmailButton>\n </Layout>\n );\n}\n\nEmailVerification.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: { verifyUrl: \"http://localhost:8002/verify?token=demo\" },\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"accessGranted\"];\n\nexport const subject = (_ctx: TemplateContext, params: Params) =>\n `You now have access to ${params.contentTitle}`;\n\nconst PORTAL_PATH: Record<Exclude<Params[\"contentType\"], \"bundle\">, string> = {\n course: \"courses\",\n download: \"downloads\",\n community: \"communities\",\n event: \"events\",\n};\n\nconst BUTTON: Record<Params[\"contentType\"], string> = {\n course: \"Start learning\",\n download: \"View download\",\n community: \"Open community\",\n event: \"Open event\",\n bundle: \"Open your library\",\n};\n\nfunction hrefOf(ctx: TemplateContext, params: Params): string {\n return params.contentType === \"bundle\"\n ? ctx.studentPortalUrl\n : `${ctx.studentPortalUrl}/${PORTAL_PATH[params.contentType]}/${params.contentId}`;\n}\n\nexport default function AccessGranted({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading={`${params.contentTitle} is ready for you`}>\n <Paragraph>\n {params.contentType === \"bundle\"\n ? \"You've been granted access to everything it includes. Jump in whenever you're ready.\"\n : \"You've been granted access. Jump in whenever you're ready.\"}\n </Paragraph>\n <EmailButton href={hrefOf(ctx, params)}>{BUTTON[params.contentType]}</EmailButton>\n </Layout>\n );\n}\n\nAccessGranted.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n contentTitle: \"Fly Tying 101\",\n contentId: \"demo\",\n contentType: \"course\",\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"accessRevoked\"];\n\nexport const subject = (_ctx: TemplateContext, params: Params) =>\n `Your access to ${params.contentTitle} has ended`;\n\nexport default function AccessRevoked({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Access ended\">\n <Paragraph>\n Your access to {params.contentTitle} has ended. If you think this is a mistake, reply to\n this email.\n </Paragraph>\n </Layout>\n );\n}\n\nAccessRevoked.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n contentTitle: \"Fly Tying 101\",\n },\n};\n","import type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\ntype Params = EmailTemplateParams[\"courseCompleted\"];\n\nexport const subject = (_ctx: TemplateContext, params: Params) =>\n `You completed ${params.courseTitle} ๐ŸŽ‰`;\n\nexport default function CourseCompleted({ ctx, params }: { ctx: TemplateContext; params: Params }) {\n return (\n <Layout ctx={ctx} heading=\"Congratulations!\">\n <Paragraph>You've completed {params.courseTitle}. Nice work.</Paragraph>\n </Layout>\n );\n}\n\nCourseCompleted.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n courseTitle: \"Fly Tying 101\",\n },\n};\n","import type { JSX } from \"react\";\nimport type { EmailTemplateParams, TemplateContext } from \"@headless-lms/core/types\";\nimport { Link, Section, Text } from \"@react-email/components\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\nexport function portal(ctx: TemplateContext, path: string): string {\n return `${ctx.studentPortalUrl}${path}`;\n}\n\nexport function defineEmail<K extends keyof EmailTemplateParams>(opts: {\n subject: (ctx: TemplateContext, params: EmailTemplateParams[K]) => string;\n heading: (params: EmailTemplateParams[K]) => string;\n lines: (params: EmailTemplateParams[K]) => string[];\n button?: (\n ctx: TemplateContext,\n params: EmailTemplateParams[K],\n ) => { href: string; label: string };\n preview: EmailTemplateParams[K];\n}): {\n subject: (ctx: TemplateContext, params: EmailTemplateParams[K]) => string;\n Component: (props: { ctx: TemplateContext; params: EmailTemplateParams[K] }) => JSX.Element;\n} {\n function Component({ ctx, params }: { ctx: TemplateContext; params: EmailTemplateParams[K] }) {\n const button = opts.button?.(ctx, params);\n return (\n <Layout ctx={ctx} heading={opts.heading(params)}>\n {opts.lines(params).map((line, index) => (\n <Paragraph key={index}>{line}</Paragraph>\n ))}\n {button ? <EmailButton href={button.href}>{button.label}</EmailButton> : null}\n </Layout>\n );\n }\n Component.PreviewProps = { ctx: PREVIEW_CTX, params: opts.preview };\n return { subject: opts.subject, Component };\n}\n\nconst community = (ctx: TemplateContext, id: string) => portal(ctx, `/communities/${id}`);\nconst space = (ctx: TemplateContext, communityId: string, spaceId: string) =>\n portal(ctx, `/communities/${communityId}/spaces/${spaceId}`);\nconst post = (ctx: TemplateContext, communityId: string, postId: string) =>\n portal(ctx, `/communities/${communityId}/posts/${postId}`);\nconst comment = (ctx: TemplateContext, communityId: string, postId: string, commentId: string) =>\n `${post(ctx, communityId, postId)}#${commentId}`;\nconst chat = (ctx: TemplateContext, communityId: string, chatId: string) =>\n portal(ctx, `/communities/${communityId}/chats/${chatId}`);\n\nfunction accessEnds(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n return new Intl.DateTimeFormat(\"en-US\", {\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n timeZone: \"UTC\",\n }).format(date);\n}\n\nexport const welcomeToCommunity = defineEmail<\"welcomeToCommunity\">({\n subject: (_ctx, params) => `Welcome to ${params.communityTitle}`,\n heading: (params) => params.communityTitle,\n lines: (params) => [\n params.spaceNames.length > 0\n ? `You can open ${params.spaceNames.join(\", \")}.`\n : \"You're a member.\",\n ],\n button: (ctx, params) => ({ href: community(ctx, params.communityId), label: \"Open community\" }),\n preview: { communityTitle: \"Founders\", communityId: \"cmy_1\", spaceNames: [\"Announcements\"] },\n});\n\nexport const membershipEndingSoon = defineEmail<\"membershipEndingSoon\">({\n subject: (_ctx, params) => `${params.communityTitle} ends soon`,\n heading: (params) => `${params.communityTitle} ends soon`,\n lines: (params) => [`Your access ends ${accessEnds(params.expiresAt)}.`],\n button: (ctx, params) => ({ href: community(ctx, params.communityId), label: \"Renew\" }),\n preview: {\n communityTitle: \"Founders\",\n communityId: \"cmy_1\",\n expiresAt: \"2026-10-28T00:00:00.000Z\",\n },\n});\n\nfunction communityTitles(params: EmailTemplateParams[\"membershipEnded\"]): string {\n return params.communities.map((item) => item.communityTitle).join(\", \");\n}\n\nexport const membershipEnded = defineEmail<\"membershipEnded\">({\n subject: (_ctx, params) => `${communityTitles(params)} has ended`,\n heading: (params) => `${communityTitles(params)} has ended`,\n lines: (params) => [\n params.communities.length === 1\n ? \"Your access to this community has ended.\"\n : \"Your access to these communities has ended.\",\n ],\n button: (ctx, params) => {\n const [only] = params.communities;\n return params.communities.length === 1 && only\n ? { href: community(ctx, only.communityId), label: \"Renew\" }\n : { href: portal(ctx, \"/communities\"), label: \"Open communities\" };\n },\n preview: { communities: [{ communityId: \"cmy_1\", communityTitle: \"Founders\" }] },\n});\n\nexport const newPostInSpace = defineEmail<\"newPostInSpace\">({\n subject: (_ctx, params) => `${params.authorName} posted in ${params.spaceName}`,\n heading: (params) => params.postTitle,\n lines: (params) => [`${params.authorName} in ${params.spaceName}`, params.excerpt],\n button: (ctx, params) => ({\n href: post(ctx, params.communityId, params.postId),\n label: \"Read post\",\n }),\n preview: {\n spaceName: \"Announcements\",\n postTitle: \"Hello\",\n authorName: \"Ann\",\n excerpt: \"A short note\",\n postId: \"pst_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const yourPostWasPublished = defineEmail<\"yourPostWasPublished\">({\n subject: (_ctx, params) => `Your post was published in ${params.spaceName}`,\n heading: (params) => params.postTitle,\n lines: (params) => [`It's live in ${params.spaceName}.`],\n button: (ctx, params) => ({\n href: post(ctx, params.communityId, params.postId),\n label: \"View post\",\n }),\n preview: {\n postTitle: \"Hello\",\n spaceName: \"Announcements\",\n postId: \"pst_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const yourPostWasRemoved = defineEmail<\"yourPostWasRemoved\">({\n subject: (_ctx, params) => `Your post was removed from ${params.spaceName}`,\n heading: (params) => params.postTitle,\n lines: (params) => [`It was removed from ${params.spaceName}.`],\n button: (ctx, params) => ({\n href: space(ctx, params.communityId, params.spaceId),\n label: \"Open space\",\n }),\n preview: {\n postTitle: \"Hello\",\n spaceName: \"Announcements\",\n spaceId: \"spc_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const newCommentOnPost = defineEmail<\"newCommentOnPost\">({\n subject: (_ctx, params) => `${params.commenterName} commented on ${params.postTitle}`,\n heading: (params) => params.postTitle,\n lines: (params) => [params.commenterName, params.excerpt],\n button: (ctx, params) => ({\n href: comment(ctx, params.communityId, params.postId, params.commentId),\n label: \"View comment\",\n }),\n preview: {\n postTitle: \"Hello\",\n commenterName: \"Sam\",\n excerpt: \"Nice\",\n commentId: \"cmt_1\",\n postId: \"pst_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const replyToYourComment = defineEmail<\"replyToYourComment\">({\n subject: (_ctx, params) => `${params.commenterName} replied on ${params.postTitle}`,\n heading: (params) => params.postTitle,\n lines: (params) => [params.commenterName, params.excerpt],\n button: (ctx, params) => ({\n href: comment(ctx, params.communityId, params.postId, params.commentId),\n label: \"View reply\",\n }),\n preview: {\n postTitle: \"Hello\",\n commenterName: \"Sam\",\n excerpt: \"Thanks\",\n commentId: \"cmt_2\",\n postId: \"pst_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const yourCommentWasRemoved = defineEmail<\"yourCommentWasRemoved\">({\n subject: (_ctx, params) => `Your comment was removed from ${params.postTitle}`,\n heading: (params) => params.postTitle,\n lines: () => [\"Your comment was removed.\"],\n button: (ctx, params) => ({\n href: post(ctx, params.communityId, params.postId),\n label: \"View post\",\n }),\n preview: { postTitle: \"Hello\", postId: \"pst_1\", communityId: \"cmy_1\" },\n});\n\nexport const requestApproved = defineEmail<\"requestApproved\">({\n subject: (_ctx, params) => `You're in ${params.spaceName}`,\n heading: (params) => params.spaceName,\n lines: (params) => [`Your request to join ${params.spaceName} was approved.`],\n button: (ctx, params) => ({\n href: space(ctx, params.communityId, params.spaceId),\n label: \"Open space\",\n }),\n preview: { spaceName: \"SaaS\", spaceId: \"spc_1\", communityId: \"cmy_1\" },\n});\n\nexport const requestDeclined = defineEmail<\"requestDeclined\">({\n subject: (_ctx, params) => `Request declined for ${params.spaceName}`,\n heading: (params) => params.spaceName,\n lines: (params) => [`Your request to join ${params.spaceName} was declined.`],\n button: (ctx, params) => ({ href: community(ctx, params.communityId), label: \"Open community\" }),\n preview: { spaceName: \"SaaS\", communityId: \"cmy_1\" },\n});\n\nexport const invitedToSpace = defineEmail<\"invitedToSpace\">({\n subject: (_ctx, params) => `${params.inviterName} invited you to ${params.spaceName}`,\n heading: (params) => params.spaceName,\n lines: (params) => [`${params.inviterName} invited you.`],\n button: (ctx, params) => ({\n href: space(ctx, params.communityId, params.spaceId),\n label: \"Accept\",\n }),\n preview: {\n spaceName: \"SaaS\",\n inviterName: \"Ann\",\n spaceId: \"spc_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const messageRequest = defineEmail<\"messageRequest\">({\n subject: (_ctx, params) => `${params.senderName} sent a message request`,\n heading: (params) => params.senderName,\n lines: (params) => [params.excerpt],\n button: (ctx, params) => ({\n href: chat(ctx, params.communityId, params.chatId),\n label: \"View request\",\n }),\n preview: { senderName: \"Ann\", excerpt: \"Hello\", chatId: \"cht_1\", communityId: \"cmy_1\" },\n});\n\nexport const newMessage = defineEmail<\"newMessage\">({\n subject: (_ctx, params) => `${params.senderName} in ${params.chatTitle}`,\n heading: (params) => params.chatTitle,\n lines: (params) => [`${params.senderName}: ${params.excerpt}`],\n button: (ctx, params) => ({\n href: chat(ctx, params.communityId, params.chatId),\n label: \"Open chat\",\n }),\n preview: {\n senderName: \"Ann\",\n chatTitle: \"Group chat\",\n excerpt: \"Hello\",\n chatId: \"cht_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const addedToGroupChat = defineEmail<\"addedToGroupChat\">({\n subject: (_ctx, params) => `${params.adderName} added you to a chat`,\n heading: () => \"You were added to a chat\",\n lines: (params) => [`${params.adderName} added you.`, params.participantNames.join(\", \")],\n button: (ctx, params) => ({\n href: chat(ctx, params.communityId, params.chatId),\n label: \"Open chat\",\n }),\n preview: {\n adderName: \"Ann\",\n participantNames: [\"Ann\", \"Sam\"],\n chatId: \"cht_1\",\n communityId: \"cmy_1\",\n },\n});\n\nconst ROLE_PATH: Record<string, string> = {\n course: \"courses\",\n download: \"downloads\",\n community: \"communities\",\n event: \"events\",\n};\n\nexport const roleAssigned = defineEmail<\"roleAssigned\">({\n subject: (_ctx, params) => `You are now ${params.roleName} ${params.place}`,\n heading: (params) => `You are now ${params.roleName}`,\n lines: (params) => [`You are now ${params.roleName} ${params.place}.`],\n button: (ctx, params) =>\n params.contentId !== null && params.contentType !== null\n ? {\n href: `${ctx.baseUrl}/${ROLE_PATH[params.contentType] ?? \"\"}/${params.contentId}`,\n label: \"Open\",\n }\n : { href: ctx.baseUrl, label: \"Open\" },\n preview: {\n roleName: \"Moderator\",\n place: \"of Founders\",\n contentId: \"cmy_1\",\n contentType: \"community\",\n },\n});\n\ntype DigestParams = EmailTemplateParams[\"digest\"];\n\nfunction commentsLabel(count: number): string {\n return count === 1 ? \"1 comment\" : `${count} comments`;\n}\n\nfunction Digest({ ctx, params }: { ctx: TemplateContext; params: DigestParams }) {\n return (\n <Layout ctx={ctx} heading={`${params.communityTitle} digest`}>\n <Paragraph>{\"Here's what you haven't seen.\"}</Paragraph>\n {params.posts.map((item) => (\n <Section key={item.postId} className=\"my-[12px]\">\n <Link\n href={post(ctx, params.communityId, item.postId)}\n className=\"text-[16px] font-semibold text-[#18181b]\"\n >\n {item.title}\n </Link>\n <Text className=\"my-[2px] text-[14px] leading-[1.4] text-[#6b7280]\">\n {`${item.authorName} in ${item.spaceName} ยท ${commentsLabel(item.commentCount)}`}\n </Text>\n </Section>\n ))}\n <EmailButton href={community(ctx, params.communityId)}>Open community</EmailButton>\n </Layout>\n );\n}\n\nDigest.PreviewProps = {\n ctx: PREVIEW_CTX,\n params: {\n communityTitle: \"Founders\",\n communityId: \"cmy_1\",\n from: \"2026-10-29T07:00:00.000Z\",\n to: \"2026-11-05T07:00:00.000Z\",\n posts: [\n {\n postId: \"pst_1\",\n title: \"Welcome, everyone\",\n authorName: \"Sam\",\n spaceName: \"Announcements\",\n commentCount: 4,\n },\n ],\n },\n};\n\nexport const digest = {\n subject: (_ctx: TemplateContext, params: DigestParams) => `${params.communityTitle} digest`,\n Component: Digest,\n};\n\nexport const postAwaitingReview = defineEmail<\"postAwaitingReview\">({\n subject: (_ctx, params) => `Post awaiting review in ${params.spaceName}`,\n heading: (params) => params.postTitle,\n lines: (params) => [`${params.authorName} submitted a post in ${params.spaceName}.`],\n button: (ctx, params) => ({\n href: space(ctx, params.communityId, params.spaceId),\n label: \"Review\",\n }),\n preview: {\n spaceName: \"Announcements\",\n postTitle: \"Hello\",\n authorName: \"Sam\",\n spaceId: \"spc_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const joinRequest = defineEmail<\"joinRequest\">({\n subject: (_ctx, params) => `${params.memberName} requested ${params.spaceName}`,\n heading: (params) => params.spaceName,\n lines: (params) => [`${params.memberName} asked to join. Seats left: ${params.seatsLeft}.`],\n button: (ctx, params) => ({\n href: space(ctx, params.communityId, params.spaceId),\n label: \"Review request\",\n }),\n preview: {\n spaceName: \"SaaS\",\n memberName: \"Sam\",\n seatsLeft: \"3\",\n spaceId: \"spc_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const somethingWasFlagged = defineEmail<\"somethingWasFlagged\">({\n subject: (_ctx, params) => `Something was flagged in ${params.spaceName}`,\n heading: (params) => params.spaceName,\n lines: (params) => [params.reason, params.excerpt],\n button: (ctx, params) => ({\n href: space(ctx, params.communityId, params.spaceId),\n label: \"Review\",\n }),\n preview: {\n spaceName: \"Announcements\",\n excerpt: \"Hello\",\n reason: \"Spam\",\n spaceId: \"spc_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const messageWasFlagged = defineEmail<\"messageWasFlagged\">({\n subject: () => \"A message was flagged\",\n heading: () => \"A message was flagged\",\n lines: (params) => [params.reason],\n button: (ctx, params) => ({ href: community(ctx, params.communityId), label: \"Review\" }),\n preview: { reason: \"Spam\", communityId: \"cmy_1\" },\n});\n\nexport const postReacted = defineEmail<\"postReacted\">({\n subject: (_ctx, params) => `${params.reactorName} reacted to your post`,\n heading: (params) => params.postTitle,\n lines: (params) => [`${params.reactorName} reacted ${params.reaction} to your post.`],\n button: (ctx, params) => ({\n href: post(ctx, params.communityId, params.postId),\n label: \"View post\",\n }),\n preview: {\n postTitle: \"Hello\",\n reactorName: \"Sam\",\n reaction: \"๐Ÿ‘\",\n postId: \"pst_1\",\n communityId: \"cmy_1\",\n },\n});\n\nexport const commentReacted = defineEmail<\"commentReacted\">({\n subject: (_ctx, params) => `${params.reactorName} reacted to your comment`,\n heading: (params) => params.postTitle,\n lines: (params) => [`${params.reactorName} reacted ${params.reaction} to:`, params.excerpt],\n button: (ctx, params) => ({\n href: comment(ctx, params.communityId, params.postId, params.commentId),\n label: \"View comment\",\n }),\n preview: {\n postTitle: \"Hello\",\n excerpt: \"Nice\",\n reactorName: \"Sam\",\n reaction: \"๐Ÿ‘\",\n commentId: \"cmt_1\",\n postId: \"pst_1\",\n communityId: \"cmy_1\",\n },\n});\n\nfunction mentionedIn(params: EmailTemplateParams[\"mention\"]): string {\n return \"postTitle\" in params ? params.postTitle : params.chatTitle;\n}\n\nexport const mention = defineEmail<\"mention\">({\n subject: (_ctx, params) => `${params.authorName} mentioned you in ${mentionedIn(params)}`,\n heading: (params) => mentionedIn(params),\n lines: (params) => [params.authorName, params.excerpt],\n button: (ctx, params) =>\n \"postTitle\" in params\n ? {\n href: params.commentId\n ? comment(ctx, params.communityId, params.postId, params.commentId)\n : post(ctx, params.communityId, params.postId),\n label: \"View\",\n }\n : { href: chat(ctx, params.communityId, params.chatId), label: \"Open chat\" },\n preview: {\n authorName: \"Sam\",\n excerpt: \"Thanks @Ann\",\n communityId: \"cmy_1\",\n postTitle: \"Hello\",\n postId: \"pst_1\",\n commentId: \"cmt_1\",\n },\n});\n\nexport const messageReacted = defineEmail<\"messageReacted\">({\n subject: (_ctx, params) => `${params.reactorName} reacted to your message`,\n heading: () => \"A reaction to your message\",\n lines: (params) => [`${params.reactorName} reacted ${params.reaction} to:`, params.excerpt],\n button: (ctx, params) => ({\n href: chat(ctx, params.communityId, params.chatId),\n label: \"Open chat\",\n }),\n preview: {\n excerpt: \"Hello\",\n reactorName: \"Sam\",\n reaction: \"๐Ÿ‘\",\n chatId: \"cht_1\",\n communityId: \"cmy_1\",\n },\n});\n","import type { TemplateContext } from \"@headless-lms/core/types\";\nimport { defineEmail, portal } from \"./community.js\";\n\nconst activity = (ctx: TemplateContext, courseId: string, activityId: string) =>\n portal(ctx, `/courses/${courseId}?activity=${activityId}`);\n\nexport const courseActivityAdded = defineEmail<\"courseActivityAdded\">({\n subject: (_ctx, params) => `New in ${params.courseTitle}: ${params.activityTitle}`,\n heading: (params) => params.activityTitle,\n lines: (params) => [`${params.courseTitle}, ${params.moduleTitle}`],\n button: (ctx, params) => ({\n href: activity(ctx, params.courseId, params.activityId),\n label: \"Open lesson\",\n }),\n preview: {\n courseTitle: \"Fly Tying 101\",\n moduleTitle: \"Basics\",\n activityTitle: \"Choosing hooks\",\n courseId: \"crs_1\",\n activityId: \"act_1\",\n },\n});\n\nexport const activityCommentCreated = defineEmail<\"activityCommentCreated\">({\n subject: (_ctx, params) => `${params.commenterName} commented on ${params.activityTitle}`,\n heading: (params) => params.activityTitle,\n lines: (params) => [params.courseTitle, params.commenterName, params.excerpt],\n button: (ctx, params) => ({\n href: activity(ctx, params.courseId, params.activityId),\n label: \"View comment\",\n }),\n preview: {\n activityTitle: \"Choosing hooks\",\n courseTitle: \"Fly Tying 101\",\n commenterName: \"Sam\",\n excerpt: \"Nice\",\n courseId: \"crs_1\",\n activityId: \"act_1\",\n commentId: \"cmt_1\",\n },\n});\n\nexport const activityCommentRemoved = defineEmail<\"activityCommentRemoved\">({\n subject: (_ctx, params) => `Your comment was removed from ${params.activityTitle}`,\n heading: (params) => params.activityTitle,\n lines: (params) => [`Your comment in ${params.courseTitle} was removed.`],\n button: (ctx, params) => ({\n href: activity(ctx, params.courseId, params.activityId),\n label: \"Open lesson\",\n }),\n preview: {\n activityTitle: \"Choosing hooks\",\n courseTitle: \"Fly Tying 101\",\n courseId: \"crs_1\",\n activityId: \"act_1\",\n },\n});\n\nexport const activityCommentReacted = defineEmail<\"activityCommentReacted\">({\n subject: (_ctx, params) => `${params.reactorName} reacted to your comment`,\n heading: (params) => params.activityTitle,\n lines: (params) => [`${params.reactorName} reacted ${params.reaction} to:`, params.excerpt],\n button: (ctx, params) => ({\n href: activity(ctx, params.courseId, params.activityId),\n label: \"View comment\",\n }),\n preview: {\n activityTitle: \"Choosing hooks\",\n courseTitle: \"Fly Tying 101\",\n excerpt: \"Nice\",\n reactorName: \"Sam\",\n reaction: \"๐Ÿ‘\",\n courseId: \"crs_1\",\n activityId: \"act_1\",\n commentId: \"cmt_1\",\n },\n});\n\nexport const activityCommentFlagged = defineEmail<\"activityCommentFlagged\">({\n subject: (_ctx, params) => `A comment was flagged in ${params.activityTitle}`,\n heading: (params) => params.activityTitle,\n lines: (params) => [params.courseTitle, params.reason, params.excerpt],\n button: (ctx, params) => ({\n href: activity(ctx, params.courseId, params.activityId),\n label: \"Review\",\n }),\n preview: {\n activityTitle: \"Choosing hooks\",\n courseTitle: \"Fly Tying 101\",\n excerpt: \"Hello\",\n reason: \"Spam\",\n courseId: \"crs_1\",\n activityId: \"act_1\",\n },\n});\n\nexport const activityMention = defineEmail<\"activityMention\">({\n subject: (_ctx, params) => `${params.authorName} mentioned you in ${params.activityTitle}`,\n heading: (params) => params.activityTitle,\n lines: (params) => [params.courseTitle, params.authorName, params.excerpt],\n button: (ctx, params) => ({\n href: activity(ctx, params.courseId, params.activityId),\n label: \"View\",\n }),\n preview: {\n authorName: \"Sam\",\n excerpt: \"Thanks @Ann\",\n activityTitle: \"Choosing hooks\",\n courseTitle: \"Fly Tying 101\",\n courseId: \"crs_1\",\n activityId: \"act_1\",\n },\n});\n","import type {\n EmailTemplateParams,\n EventEmailParams,\n TemplateContext,\n} from \"@headless-lms/core/types\";\nimport { Link, Section } from \"@react-email/components\";\nimport { defineEmail, portal } from \"./community.js\";\nimport { EmailButton, Layout, Paragraph, PREVIEW_CTX } from \"./layout.js\";\n\nconst PREVIEW_EVENT: EventEmailParams = {\n eventId: \"evn_1\",\n eventTitle: \"Conversation practice\",\n startsAt: \"2026-05-12T16:00:00.000Z\",\n endsAt: \"2026-05-12T17:00:00.000Z\",\n timeZone: \"Europe/London\",\n};\n\nexport function eventPage(ctx: TemplateContext, eventId: string): string {\n return portal(ctx, `/events/${eventId}`);\n}\n\nfunction formatIn(value: string, timeZone: string, options: Intl.DateTimeFormatOptions): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n try {\n return new Intl.DateTimeFormat(\"en-US\", { ...options, timeZone }).format(date);\n } catch {\n return new Intl.DateTimeFormat(\"en-US\", { ...options, timeZone: \"UTC\" }).format(date);\n }\n}\n\nexport function eventWhen(params: EventEmailParams): string {\n const day = formatIn(params.startsAt, params.timeZone, {\n weekday: \"long\",\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n });\n const time = { hour: \"numeric\", minute: \"2-digit\" } as const;\n const from = formatIn(params.startsAt, params.timeZone, time);\n const to = formatIn(params.endsAt, params.timeZone, time);\n return `${day}, ${from} โ€“ ${to} (${params.timeZone})`;\n}\n\nfunction calendarStamp(value: string): string {\n return new Date(value)\n .toISOString()\n .replace(/[-:]/g, \"\")\n .replace(/\\.\\d{3}/, \"\");\n}\n\nexport function googleCalendarUrl(ctx: TemplateContext, params: EventEmailParams): string {\n const query = new URLSearchParams({\n action: \"TEMPLATE\",\n text: params.eventTitle,\n dates: `${calendarStamp(params.startsAt)}/${calendarStamp(params.endsAt)}`,\n details: eventPage(ctx, params.eventId),\n ctz: params.timeZone,\n });\n return `https://calendar.google.com/calendar/render?${query.toString()}`;\n}\n\nexport function outlookCalendarUrl(ctx: TemplateContext, params: EventEmailParams): string {\n const query = new URLSearchParams({\n path: \"/calendar/action/compose\",\n rru: \"addevent\",\n subject: params.eventTitle,\n startdt: new Date(params.startsAt).toISOString(),\n enddt: new Date(params.endsAt).toISOString(),\n body: eventPage(ctx, params.eventId),\n });\n return `https://outlook.live.com/calendar/0/action/compose?${query.toString()}`;\n}\n\ntype Granted = EmailTemplateParams[\"eventGranted\"];\n\nfunction EventGranted({ ctx, params }: { ctx: TemplateContext; params: Granted }) {\n return (\n <Layout ctx={ctx} heading={`You're going to ${params.eventTitle}`}>\n <Paragraph>{eventWhen(params)}</Paragraph>\n <EmailButton href={eventPage(ctx, params.eventId)}>Open event</EmailButton>\n <Section>\n <Paragraph>\n <Link href={googleCalendarUrl(ctx, params)}>Add to Google Calendar</Link>\n {\" ยท \"}\n <Link href={outlookCalendarUrl(ctx, params)}>Add to Outlook</Link>\n </Paragraph>\n </Section>\n </Layout>\n );\n}\n\nEventGranted.PreviewProps = { ctx: PREVIEW_CTX, params: PREVIEW_EVENT };\n\nexport const eventGranted = {\n subject: (_ctx: TemplateContext, params: Granted) => `You're going to ${params.eventTitle}`,\n Component: EventGranted,\n};\n\nconst CHANGED: Record<EmailTemplateParams[\"eventChanged\"][\"changed\"], string> = {\n time: \"The time has changed.\",\n location: \"The location has changed. Open the event for the new details.\",\n time_and_location: \"The time and the location have changed. Open the event for the new details.\",\n};\n\nconst open = (ctx: TemplateContext, params: EventEmailParams) => ({\n href: eventPage(ctx, params.eventId),\n label: \"Open event\",\n});\n\nexport const eventStartingSoon = defineEmail<\"eventStartingSoon\">({\n subject: (_ctx, params) => `${params.eventTitle} starts in ${params.leadText}`,\n heading: (params) => `${params.eventTitle} starts in ${params.leadText}`,\n lines: (params) => [eventWhen(params), \"Open the event for the link.\"],\n button: open,\n preview: { ...PREVIEW_EVENT, leadText: \"1 hour\" },\n});\n\nexport const eventChanged = defineEmail<\"eventChanged\">({\n subject: (_ctx, params) => `${params.eventTitle} has changed`,\n heading: (params) => `${params.eventTitle} has changed`,\n lines: (params) => [CHANGED[params.changed], eventWhen(params)],\n button: open,\n preview: { ...PREVIEW_EVENT, changed: \"time\" },\n});\n\nexport const eventCanceled = defineEmail<\"eventCanceled\">({\n subject: (_ctx, params) => `${params.eventTitle} was canceled`,\n heading: (params) => `${params.eventTitle} was canceled`,\n lines: (params) => [`It was planned for ${eventWhen(params)}.`],\n button: open,\n preview: PREVIEW_EVENT,\n});\n\nexport const eventRevoked = defineEmail<\"eventRevoked\">({\n subject: (_ctx, params) => `You're no longer going to ${params.eventTitle}`,\n heading: (params) => `You're no longer going to ${params.eventTitle}`,\n lines: (params) => [`You've been removed from the event on ${eventWhen(params)}.`],\n button: open,\n preview: PREVIEW_EVENT,\n});\n","// Default TemplateRenderer: react-email components rendered at call time.\nimport { render } from \"@react-email/render\";\nimport type { JSX } from \"react\";\nimport type {\n EmailContent,\n EmailTemplateId,\n EmailTemplateParams,\n TemplateContext,\n TemplateRenderer,\n} from \"@headless-lms/core/types\";\nimport MagicLink, { subject as magicLink } from \"./emails/magic-link.js\";\nimport StudentInvite, { subject as studentInvite } from \"./emails/student-invite.js\";\nimport MemberInvite, { subject as memberInvite } from \"./emails/member-invite.js\";\nimport PasswordReset, { subject as passwordReset } from \"./emails/password-reset.js\";\nimport PasswordChanged, { subject as passwordChanged } from \"./emails/password-changed.js\";\nimport EmailVerification, { subject as emailVerification } from \"./emails/email-verification.js\";\nimport AccessGranted, { subject as accessGranted } from \"./emails/access-granted.js\";\nimport AccessRevoked, { subject as accessRevoked } from \"./emails/access-revoked.js\";\nimport CourseCompleted, { subject as courseCompleted } from \"./emails/course-completed.js\";\nimport {\n addedToGroupChat,\n commentReacted,\n digest,\n invitedToSpace,\n joinRequest,\n membershipEnded,\n membershipEndingSoon,\n mention,\n messageReacted,\n messageRequest,\n messageWasFlagged,\n newCommentOnPost,\n newMessage,\n newPostInSpace,\n postAwaitingReview,\n postReacted,\n replyToYourComment,\n requestApproved,\n requestDeclined,\n somethingWasFlagged,\n welcomeToCommunity,\n roleAssigned,\n yourCommentWasRemoved,\n yourPostWasPublished,\n yourPostWasRemoved,\n} from \"./emails/community.js\";\nimport {\n activityCommentCreated,\n activityCommentFlagged,\n activityCommentReacted,\n activityCommentRemoved,\n activityMention,\n courseActivityAdded,\n} from \"./emails/course-activity.js\";\nimport {\n eventCanceled,\n eventChanged,\n eventGranted,\n eventRevoked,\n eventStartingSoon,\n} from \"./emails/events.js\";\n\ninterface Entry<K extends EmailTemplateId> {\n subject: (ctx: TemplateContext, params: EmailTemplateParams[K]) => string;\n Component: (props: { ctx: TemplateContext; params: EmailTemplateParams[K] }) => JSX.Element;\n}\n\n// The catalog is closed: a missing key here is a compile error.\nconst registry: { [K in EmailTemplateId]: Entry<K> } = {\n magicLink: { subject: magicLink, Component: MagicLink },\n studentInvite: { subject: studentInvite, Component: StudentInvite },\n memberInvite: { subject: memberInvite, Component: MemberInvite },\n passwordReset: { subject: passwordReset, Component: PasswordReset },\n passwordChanged: { subject: passwordChanged, Component: PasswordChanged },\n emailVerification: { subject: emailVerification, Component: EmailVerification },\n accessGranted: { subject: accessGranted, Component: AccessGranted },\n accessRevoked: { subject: accessRevoked, Component: AccessRevoked },\n courseCompleted: { subject: courseCompleted, Component: CourseCompleted },\n welcomeToCommunity: {\n subject: welcomeToCommunity.subject,\n Component: welcomeToCommunity.Component,\n },\n membershipEndingSoon: {\n subject: membershipEndingSoon.subject,\n Component: membershipEndingSoon.Component,\n },\n membershipEnded: { subject: membershipEnded.subject, Component: membershipEnded.Component },\n newPostInSpace: { subject: newPostInSpace.subject, Component: newPostInSpace.Component },\n yourPostWasPublished: {\n subject: yourPostWasPublished.subject,\n Component: yourPostWasPublished.Component,\n },\n yourPostWasRemoved: {\n subject: yourPostWasRemoved.subject,\n Component: yourPostWasRemoved.Component,\n },\n newCommentOnPost: { subject: newCommentOnPost.subject, Component: newCommentOnPost.Component },\n replyToYourComment: {\n subject: replyToYourComment.subject,\n Component: replyToYourComment.Component,\n },\n yourCommentWasRemoved: {\n subject: yourCommentWasRemoved.subject,\n Component: yourCommentWasRemoved.Component,\n },\n requestApproved: { subject: requestApproved.subject, Component: requestApproved.Component },\n requestDeclined: { subject: requestDeclined.subject, Component: requestDeclined.Component },\n invitedToSpace: { subject: invitedToSpace.subject, Component: invitedToSpace.Component },\n messageRequest: { subject: messageRequest.subject, Component: messageRequest.Component },\n newMessage: { subject: newMessage.subject, Component: newMessage.Component },\n addedToGroupChat: { subject: addedToGroupChat.subject, Component: addedToGroupChat.Component },\n roleAssigned: { subject: roleAssigned.subject, Component: roleAssigned.Component },\n digest: { subject: digest.subject, Component: digest.Component },\n postAwaitingReview: {\n subject: postAwaitingReview.subject,\n Component: postAwaitingReview.Component,\n },\n joinRequest: { subject: joinRequest.subject, Component: joinRequest.Component },\n somethingWasFlagged: {\n subject: somethingWasFlagged.subject,\n Component: somethingWasFlagged.Component,\n },\n messageWasFlagged: {\n subject: messageWasFlagged.subject,\n Component: messageWasFlagged.Component,\n },\n postReacted: { subject: postReacted.subject, Component: postReacted.Component },\n commentReacted: { subject: commentReacted.subject, Component: commentReacted.Component },\n mention: { subject: mention.subject, Component: mention.Component },\n messageReacted: { subject: messageReacted.subject, Component: messageReacted.Component },\n courseActivityAdded: {\n subject: courseActivityAdded.subject,\n Component: courseActivityAdded.Component,\n },\n activityCommentCreated: {\n subject: activityCommentCreated.subject,\n Component: activityCommentCreated.Component,\n },\n activityCommentRemoved: {\n subject: activityCommentRemoved.subject,\n Component: activityCommentRemoved.Component,\n },\n activityCommentReacted: {\n subject: activityCommentReacted.subject,\n Component: activityCommentReacted.Component,\n },\n activityCommentFlagged: {\n subject: activityCommentFlagged.subject,\n Component: activityCommentFlagged.Component,\n },\n activityMention: { subject: activityMention.subject, Component: activityMention.Component },\n eventGranted: { subject: eventGranted.subject, Component: eventGranted.Component },\n eventStartingSoon: {\n subject: eventStartingSoon.subject,\n Component: eventStartingSoon.Component,\n },\n eventChanged: { subject: eventChanged.subject, Component: eventChanged.Component },\n eventCanceled: { subject: eventCanceled.subject, Component: eventCanceled.Component },\n eventRevoked: { subject: eventRevoked.subject, Component: eventRevoked.Component },\n};\n\nexport class ReactEmailTemplateRenderer implements TemplateRenderer {\n async render<K extends EmailTemplateId>(\n id: K,\n ctx: TemplateContext,\n params: EmailTemplateParams[K],\n ): Promise<EmailContent> {\n const entry = registry[id] as Entry<K>;\n const element = <entry.Component ctx={ctx} params={params} />;\n const [html, text] = await Promise.all([render(element), render(element, { plainText: true })]);\n return { subject: entry.subject(ctx, params), html, text };\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-lms/adapter-email-templates",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -15,7 +15,7 @@
15
15
  "@react-email/render": "^2.1.0",
16
16
  "react": "19.2.4",
17
17
  "react-dom": "19.2.4",
18
- "@headless-lms/core": "0.1.0"
18
+ "@headless-lms/core": "0.6.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@react-email/ui": "6.9.0",