@ctrl-ui/react 0.8.4 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/audio-visualizer.js +1 -1
  2. package/dist/chat-composer-editor/extensions/mention.js +4 -0
  3. package/dist/chat-layout.d.ts +5 -0
  4. package/dist/chat-layout.js +61 -20
  5. package/dist/chat-message.d.ts +5 -0
  6. package/dist/chat-message.js +19 -2
  7. package/dist/context.js +0 -2
  8. package/dist/email/email-brand.d.ts +60 -0
  9. package/dist/email/email-brand.js +101 -0
  10. package/dist/email/email-code.d.ts +18 -0
  11. package/dist/email/email-code.js +172 -0
  12. package/dist/email/email-footer.d.ts +63 -0
  13. package/dist/email/email-footer.js +98 -0
  14. package/dist/email/email.d.ts +60 -11
  15. package/dist/email/email.js +155 -24
  16. package/dist/email/templates.d.ts +54 -9
  17. package/dist/email/templates.js +314 -116
  18. package/dist/email/theme.d.ts +13 -5
  19. package/dist/email/theme.js +30 -8
  20. package/dist/hooks/use-chat-message.d.ts +1 -0
  21. package/dist/hooks/use-chat-message.js +1 -0
  22. package/dist/hooks/use-chat-thread-scroll.d.ts +8 -0
  23. package/dist/hooks/use-chat-thread-scroll.js +66 -0
  24. package/dist/hooks/use-user-ask.d.ts +6 -4
  25. package/dist/hooks/use-user-ask.js +56 -17
  26. package/dist/inline-attachment.js +1 -1
  27. package/dist/knob-contracts/action-bar-knobs.d.ts +1 -1
  28. package/dist/knob-contracts/action-bar-knobs.js +1 -1
  29. package/dist/knob-contracts/activity-knobs.d.ts +1 -1
  30. package/dist/knob-contracts/activity-knobs.js +2 -1
  31. package/dist/knob-contracts/audio-visualizer-knobs.d.ts +1 -1
  32. package/dist/knob-contracts/audio-visualizer-knobs.js +1 -0
  33. package/dist/knob-contracts/chat-composer-attachment-knobs.d.ts +1 -1
  34. package/dist/knob-contracts/chat-composer-attachment-knobs.js +2 -0
  35. package/dist/knob-contracts/chat-composer-knobs.d.ts +1 -1
  36. package/dist/knob-contracts/chat-composer-knobs.js +1 -0
  37. package/dist/knob-contracts/chat-layout-knobs.d.ts +1 -1
  38. package/dist/knob-contracts/chat-layout-knobs.js +2 -1
  39. package/dist/knob-contracts/chat-message-knobs.d.ts +1 -1
  40. package/dist/knob-contracts/chat-message-knobs.js +3 -1
  41. package/dist/knob-contracts/context-knobs.d.ts +1 -1
  42. package/dist/knob-contracts/context-knobs.js +3 -0
  43. package/dist/knob-contracts/inline-attachment-knobs.d.ts +1 -1
  44. package/dist/knob-contracts/inline-attachment-knobs.js +4 -0
  45. package/dist/knob-contracts/inline-citation-knobs.d.ts +1 -1
  46. package/dist/knob-contracts/inline-citation-knobs.js +3 -1
  47. package/dist/knob-contracts/page-layout-knobs.d.ts +4 -0
  48. package/dist/knob-contracts/page-layout-knobs.js +15 -0
  49. package/dist/knob-contracts/table-of-contents-knobs.d.ts +1 -1
  50. package/dist/knob-contracts/table-of-contents-knobs.js +3 -3
  51. package/dist/knob-contracts/task-list-knobs.d.ts +1 -1
  52. package/dist/knob-contracts/task-list-knobs.js +4 -0
  53. package/dist/knob-contracts/user-ask-knobs.d.ts +1 -1
  54. package/dist/knob-contracts/user-ask-knobs.js +4 -0
  55. package/dist/lib/phone-input-format.js +1 -1
  56. package/dist/markdown-block.js +1 -1
  57. package/dist/styles/index.css +2 -1
  58. package/dist/styles/recipes/action-bar.css +37 -5
  59. package/dist/styles/recipes/activity.css +36 -3
  60. package/dist/styles/recipes/alert.css +2 -0
  61. package/dist/styles/recipes/audio-visualizer.css +8 -1
  62. package/dist/styles/recipes/button-group.css +8 -0
  63. package/dist/styles/recipes/button.css +15 -0
  64. package/dist/styles/recipes/calendar.css +21 -0
  65. package/dist/styles/recipes/card.css +2 -0
  66. package/dist/styles/recipes/chat-composer-attachment.css +33 -2
  67. package/dist/styles/recipes/chat-composer.css +16 -2
  68. package/dist/styles/recipes/chat-layout.css +25 -1
  69. package/dist/styles/recipes/chat-message.css +69 -2
  70. package/dist/styles/recipes/choice.css +12 -0
  71. package/dist/styles/recipes/code-diff.css +1 -0
  72. package/dist/styles/recipes/code.css +25 -0
  73. package/dist/styles/recipes/context.css +30 -18
  74. package/dist/styles/recipes/dynamic-notification-input.css +6 -0
  75. package/dist/styles/recipes/dynamic-notification.css +1 -0
  76. package/dist/styles/recipes/environment-variables.css +1 -0
  77. package/dist/styles/recipes/field-parts.css +2 -0
  78. package/dist/styles/recipes/field.css +6 -0
  79. package/dist/styles/recipes/gradient-editor.css +17 -0
  80. package/dist/styles/recipes/inline-attachment.css +57 -14
  81. package/dist/styles/recipes/inline-citation.css +44 -6
  82. package/dist/styles/recipes/item.css +3 -1
  83. package/dist/styles/recipes/markdown-block.css +1 -0
  84. package/dist/styles/recipes/markdown.css +7 -0
  85. package/dist/styles/recipes/page-layout.css +203 -0
  86. package/dist/styles/recipes/pagination.css +16 -0
  87. package/dist/styles/recipes/popup-drawer.css +3 -1
  88. package/dist/styles/recipes/popup-toast.css +2 -0
  89. package/dist/styles/recipes/popup.css +8 -12
  90. package/dist/styles/recipes/range.css +24 -2
  91. package/dist/styles/recipes/rich-tooltip.css +1 -0
  92. package/dist/styles/recipes/source-badge.css +20 -0
  93. package/dist/styles/recipes/table-of-contents.css +10 -10
  94. package/dist/styles/recipes/tabs.css +16 -0
  95. package/dist/styles/recipes/task-list.css +61 -8
  96. package/dist/styles/recipes/thread-rail.css +19 -13
  97. package/dist/styles/recipes/toolbar.css +21 -0
  98. package/dist/styles/recipes/transcript-divider.css +1 -0
  99. package/dist/styles/recipes/user-ask.css +59 -16
  100. package/dist/styles/theme.css +34 -0
  101. package/dist/thread-rail.js +1 -1
  102. package/dist/ui/alert-dialog.js +2 -2
  103. package/dist/ui/autocomplete.js +1 -1
  104. package/dist/ui/color-picker.js +4 -4
  105. package/dist/ui/combobox.js +1 -1
  106. package/dist/ui/command.d.ts +5 -3
  107. package/dist/ui/command.js +27 -3
  108. package/dist/ui/context-menu.js +2 -2
  109. package/dist/ui/dialog.js +2 -2
  110. package/dist/ui/drawer.js +2 -2
  111. package/dist/ui/dropdown-menu.js +1 -1
  112. package/dist/ui/dropzone.js +4 -1
  113. package/dist/ui/gradient-editor.js +2 -2
  114. package/dist/ui/hover-card.js +1 -1
  115. package/dist/ui/infinite-canvas.js +1 -0
  116. package/dist/ui/menubar.js +2 -2
  117. package/dist/ui/navigation-menu.js +1 -1
  118. package/dist/ui/number-field.js +1 -1
  119. package/dist/ui/page-layout.d.ts +44 -0
  120. package/dist/ui/page-layout.js +108 -0
  121. package/dist/ui/phone-input.js +4 -4
  122. package/dist/ui/popover.js +1 -1
  123. package/dist/ui/resizable.js +1 -1
  124. package/dist/ui/rich-tooltip.js +1 -1
  125. package/dist/ui/select.js +1 -1
  126. package/dist/ui/sheet.js +2 -2
  127. package/dist/ui/sidebar-resize-rail.js +1 -1
  128. package/dist/ui/slider.js +1 -1
  129. package/dist/ui/toast.js +2 -2
  130. package/dist/ui/tooltip.js +1 -1
  131. package/dist/ui/trigger-menu.js +1 -1
  132. package/dist/user-ask.d.ts +5 -3
  133. package/dist/user-ask.js +38 -13
  134. package/package.json +3 -2
@@ -1,31 +1,25 @@
1
- import { EmailButton, EmailHeading, EmailLayout, EmailLink, EmailText } from "./email.js";
1
+ import { EmailBulletList, EmailButton, EmailCaption, EmailColumns, EmailDetailRow, EmailDivider, EmailHeading, EmailLayout, EmailLink, EmailOneTimeCode, EmailPanel, EmailSection, EmailText } from "./email.js";
2
+ import { EmailBrandFooter, EmailBrandHeader } from "./email-brand.js";
3
+ import { EmailCodeBlock, EmailInlineCode, EmailMarkdown } from "./email-code.js";
2
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { Column, Hr, Img, Row, Section } from "react-email";
5
+ import { Column, Img, Row } from "react-email";
4
6
  //#region src/email/templates.tsx
5
- function EmailFooter({ brand, children }) {
6
- return /* @__PURE__ */ jsxs(Fragment, { children: [
7
- /* @__PURE__ */ jsx(Hr, { className: "my-6 border-0 border-t border-solid border-t-border" }),
8
- /* @__PURE__ */ jsx(EmailText, {
9
- tone: "muted",
10
- className: "mb-1 text-caption",
11
- children: brand
12
- }),
13
- /* @__PURE__ */ jsx(EmailText, {
14
- tone: "muted",
15
- className: "mb-0 text-caption",
16
- children
17
- })
18
- ] });
19
- }
20
- function InvitationEmail({ theme, brand, footer, inviter, workspace, inviteUrl }) {
21
- return /* @__PURE__ */ jsxs(EmailLayout, {
7
+ function InvitationEmail({ theme, variant, head, brand, browserUrl, footer, inviter, workspace, inviteUrl }) {
8
+ const layout = {
22
9
  theme,
10
+ variant,
11
+ head,
12
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
13
+ footerPlacement: footer.placement
14
+ };
15
+ return /* @__PURE__ */ jsxs(EmailLayout, {
16
+ ...layout,
23
17
  preview: `${inviter} invited you to ${workspace}`,
24
18
  children: [
25
- /* @__PURE__ */ jsx(EmailText, {
26
- tone: "muted",
27
- className: "mb-8 text-caption",
28
- children: brand
19
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
20
+ brand,
21
+ browserUrl,
22
+ colorScheme: theme.colorScheme
29
23
  }),
30
24
  /* @__PURE__ */ jsx(EmailHeading, { children: "A place for your next idea." }),
31
25
  /* @__PURE__ */ jsxs(EmailText, { children: [
@@ -34,36 +28,43 @@ function InvitationEmail({ theme, brand, footer, inviter, workspace, inviteUrl }
34
28
  /* @__PURE__ */ jsx("strong", { children: workspace }),
35
29
  ". Bring your work, share a little inspiration, and make something together."
36
30
  ] }),
37
- /* @__PURE__ */ jsxs(Section, {
38
- className: "my-6 rounded-panel bg-muted p-5",
39
- children: [/* @__PURE__ */ jsx(EmailHeading, {
40
- as: "h3",
41
- children: "Your team is waiting"
42
- }), /* @__PURE__ */ jsx(EmailText, {
43
- className: "mb-0",
44
- children: "Projects, conversations, and the details that move work forward. All in one shared space."
45
- })]
46
- }),
31
+ /* @__PURE__ */ jsxs(EmailPanel, { children: [/* @__PURE__ */ jsx(EmailHeading, {
32
+ as: "h3",
33
+ children: "Your team is waiting"
34
+ }), /* @__PURE__ */ jsx(EmailText, {
35
+ className: "mb-0",
36
+ children: "Projects, conversations, and the details that move work forward. All in one shared space."
37
+ })] }),
47
38
  /* @__PURE__ */ jsxs(EmailButton, {
48
39
  href: inviteUrl,
40
+ width: "full",
49
41
  children: ["Join ", workspace]
50
- }),
51
- /* @__PURE__ */ jsx(EmailFooter, {
52
- brand,
53
- children: footer
54
42
  })
55
43
  ]
56
44
  });
57
45
  }
58
- function ProductEmail({ theme, brand, footer, title, description, imageUrl, imageAlt, actionUrl }) {
59
- return /* @__PURE__ */ jsxs(EmailLayout, {
46
+ function ProductEmail({ theme, variant, head, brand, browserUrl, footer, title, description, imageUrl, imageAlt, highlights = [], actionUrl }) {
47
+ const layout = {
60
48
  theme,
49
+ variant,
50
+ head,
51
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
52
+ footerPlacement: footer.placement
53
+ };
54
+ return /* @__PURE__ */ jsxs(EmailLayout, {
55
+ ...layout,
61
56
  preview: title,
62
57
  children: [
63
- /* @__PURE__ */ jsxs(EmailText, {
64
- tone: "muted",
65
- className: "mb-6 text-caption",
66
- children: [brand, " / NEW RELEASE"]
58
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
59
+ brand,
60
+ browserUrl,
61
+ colorScheme: theme.colorScheme,
62
+ align: "center"
63
+ }),
64
+ /* @__PURE__ */ jsx(EmailCaption, {
65
+ align: "center",
66
+ className: "mb-6",
67
+ children: "ANNOUNCEMENT"
67
68
  }),
68
69
  /* @__PURE__ */ jsx(Img, {
69
70
  src: imageUrl,
@@ -71,45 +72,74 @@ function ProductEmail({ theme, brand, footer, title, description, imageUrl, imag
71
72
  width: "552",
72
73
  className: "mb-6 block h-auto w-full rounded-scene"
73
74
  }),
74
- /* @__PURE__ */ jsx(EmailHeading, { children: title }),
75
- /* @__PURE__ */ jsx(EmailText, { children: description }),
76
- /* @__PURE__ */ jsx(EmailButton, {
77
- href: actionUrl,
78
- children: "Explore what’s new"
75
+ /* @__PURE__ */ jsx(EmailHeading, {
76
+ size: "display",
77
+ align: "center",
78
+ children: title
79
79
  }),
80
- /* @__PURE__ */ jsx(EmailFooter, {
81
- brand,
82
- children: footer
80
+ /* @__PURE__ */ jsx(EmailText, {
81
+ align: "center",
82
+ children: description
83
+ }),
84
+ /* @__PURE__ */ jsx(EmailColumns, { children: highlights.map((highlight) => /* @__PURE__ */ jsxs(EmailSection, {
85
+ align: "center",
86
+ children: [/* @__PURE__ */ jsx(EmailHeading, {
87
+ as: "h4",
88
+ align: "center",
89
+ className: "mb-1",
90
+ children: highlight.title
91
+ }), /* @__PURE__ */ jsx(EmailCaption, {
92
+ align: "center",
93
+ className: "mb-0",
94
+ children: highlight.description
95
+ })]
96
+ }, highlight.title)) }),
97
+ /* @__PURE__ */ jsx(EmailSection, {
98
+ align: "center",
99
+ children: /* @__PURE__ */ jsx(EmailButton, {
100
+ href: actionUrl,
101
+ children: "Explore what’s new"
102
+ })
83
103
  })
84
104
  ]
85
105
  });
86
106
  }
87
- function EditorialEmail({ theme, brand, footer, title, description, imageUrl, imageAlt, articleUrl }) {
88
- return /* @__PURE__ */ jsxs(EmailLayout, {
107
+ function EditorialEmail({ theme, variant, head, brand, browserUrl, footer, title, description, imageUrl, imageAlt, articleUrl }) {
108
+ const layout = {
89
109
  theme,
110
+ variant,
111
+ head,
112
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
113
+ footerPlacement: footer.placement
114
+ };
115
+ return /* @__PURE__ */ jsxs(EmailLayout, {
116
+ ...layout,
90
117
  preview: title,
91
118
  children: [
92
- /* @__PURE__ */ jsxs(EmailText, {
93
- tone: "muted",
94
- className: "mb-6 text-caption",
95
- children: [brand, " / IN GOOD COMPANY"]
96
- }),
97
- /* @__PURE__ */ jsx(EmailHeading, { children: "Fresh perspectives." }),
98
- /* @__PURE__ */ jsxs(Row, { children: [/* @__PURE__ */ jsx(Column, {
99
- width: "36%",
100
- className: "align-top",
101
- children: /* @__PURE__ */ jsx(Img, {
119
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
120
+ brand,
121
+ browserUrl,
122
+ colorScheme: theme.colorScheme
123
+ }),
124
+ /* @__PURE__ */ jsx(EmailCaption, {
125
+ className: "mb-6",
126
+ children: "IN GOOD COMPANY"
127
+ }),
128
+ /* @__PURE__ */ jsx(EmailHeading, {
129
+ size: "heading-2",
130
+ children: "Fresh perspectives."
131
+ }),
132
+ /* @__PURE__ */ jsxs(EmailColumns, {
133
+ widths: ["36%", "64%"],
134
+ children: [/* @__PURE__ */ jsx(Img, {
102
135
  src: imageUrl,
103
136
  alt: imageAlt,
104
137
  width: "198",
105
138
  className: "block h-auto w-full rounded-scene"
106
- })
107
- }), /* @__PURE__ */ jsxs(Column, {
108
- width: "64%",
109
- className: "pl-5 align-top",
110
- children: [
139
+ }), /* @__PURE__ */ jsxs(EmailSection, { children: [
111
140
  /* @__PURE__ */ jsx(EmailHeading, {
112
141
  as: "h2",
142
+ size: "heading-3",
113
143
  children: title
114
144
  }),
115
145
  /* @__PURE__ */ jsx(EmailText, { children: description }),
@@ -117,31 +147,45 @@ function EditorialEmail({ theme, brand, footer, title, description, imageUrl, im
117
147
  href: articleUrl,
118
148
  children: "Read the story"
119
149
  })
120
- ]
121
- })] }),
122
- /* @__PURE__ */ jsx(EmailFooter, {
123
- brand,
124
- children: footer
150
+ ] })]
125
151
  })
126
152
  ]
127
153
  });
128
154
  }
129
- function NewsletterEmail({ theme, brand, footer, articles, unsubscribeUrl }) {
130
- return /* @__PURE__ */ jsxs(EmailLayout, {
155
+ function NewsletterEmail({ theme, variant, head, brand, browserUrl, footer, articles }) {
156
+ const layout = {
131
157
  theme,
158
+ variant,
159
+ head,
160
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
161
+ footerPlacement: footer.placement
162
+ };
163
+ return /* @__PURE__ */ jsxs(EmailLayout, {
164
+ ...layout,
132
165
  preview: "A few things worth making time for.",
133
166
  children: [
134
- /* @__PURE__ */ jsxs(EmailText, {
135
- tone: "muted",
136
- className: "mb-6 text-caption",
137
- children: [brand, " / THE WEEKLY EDIT"]
167
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
168
+ brand,
169
+ browserUrl,
170
+ colorScheme: theme.colorScheme,
171
+ align: "center"
172
+ }),
173
+ /* @__PURE__ */ jsx(EmailCaption, {
174
+ align: "center",
175
+ className: "mb-6",
176
+ children: "THE WEEKLY EDIT"
177
+ }),
178
+ /* @__PURE__ */ jsx(EmailHeading, {
179
+ align: "center",
180
+ children: "A little room for inspiration."
138
181
  }),
139
- /* @__PURE__ */ jsx(EmailHeading, { children: "A little room for inspiration." }),
140
182
  /* @__PURE__ */ jsx(EmailText, {
183
+ align: "center",
141
184
  tone: "muted",
185
+ className: "mb-8",
142
186
  children: "A few things worth making time for. Stories, spaces, and ideas from our community."
143
187
  }),
144
- articles.map((article) => /* @__PURE__ */ jsxs(Section, {
188
+ articles.map((article) => /* @__PURE__ */ jsxs(EmailSection, {
145
189
  className: "mb-6",
146
190
  children: [
147
191
  /* @__PURE__ */ jsx(Img, {
@@ -160,69 +204,223 @@ function NewsletterEmail({ theme, brand, footer, articles, unsubscribeUrl }) {
160
204
  children: "Read the story"
161
205
  })
162
206
  ]
163
- }, article.href)),
164
- /* @__PURE__ */ jsx(EmailFooter, {
165
- brand,
166
- children: footer
167
- }),
168
- /* @__PURE__ */ jsx(EmailLink, {
169
- href: unsubscribeUrl,
170
- className: "text-caption",
171
- children: "Unsubscribe"
172
- })
207
+ }, article.href))
173
208
  ]
174
209
  });
175
210
  }
176
- function SummaryEmail({ theme, brand, footer, period, metrics, details, dashboardUrl }) {
177
- return /* @__PURE__ */ jsxs(EmailLayout, {
211
+ function SummaryEmail({ theme, variant, head, brand, browserUrl, footer, period, metrics, details, dashboardUrl }) {
212
+ const layout = {
178
213
  theme,
214
+ variant,
215
+ head,
216
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
217
+ footerPlacement: footer.placement
218
+ };
219
+ return /* @__PURE__ */ jsxs(EmailLayout, {
220
+ ...layout,
179
221
  preview: `Your team’s progress · ${period}`,
180
222
  children: [
181
- /* @__PURE__ */ jsxs(EmailText, {
182
- tone: "muted",
183
- className: "mb-6 text-caption",
184
- children: [
185
- brand,
186
- " / ",
187
- period
188
- ]
223
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
224
+ brand,
225
+ browserUrl,
226
+ colorScheme: theme.colorScheme
227
+ }),
228
+ /* @__PURE__ */ jsx(EmailCaption, {
229
+ className: "mb-6",
230
+ children: period
231
+ }),
232
+ /* @__PURE__ */ jsx(EmailHeading, {
233
+ size: "heading-2",
234
+ children: "Good work adds up."
189
235
  }),
190
- /* @__PURE__ */ jsx(EmailHeading, { children: "Good work adds up." }),
191
236
  /* @__PURE__ */ jsx(EmailText, { children: "Here’s what your team moved forward this week." }),
192
- /* @__PURE__ */ jsx(Section, {
193
- className: "my-6 rounded-panel bg-muted p-4",
237
+ /* @__PURE__ */ jsx(EmailPanel, {
238
+ className: "p-4",
194
239
  children: /* @__PURE__ */ jsx(Row, {
195
240
  className: "table-fixed",
196
241
  children: metrics.map((metric) => /* @__PURE__ */ jsxs(Column, {
197
242
  className: "px-2 align-top",
198
243
  children: [/* @__PURE__ */ jsx(EmailText, {
244
+ align: "center",
199
245
  className: "mb-1 text-heading-2 font-semibold",
200
246
  children: metric.value
201
- }), /* @__PURE__ */ jsx(EmailText, {
202
- tone: "muted",
203
- className: "mb-0 text-caption",
247
+ }), /* @__PURE__ */ jsx(EmailCaption, {
248
+ align: "center",
249
+ className: "mb-0",
204
250
  children: metric.label
205
251
  })]
206
252
  }, metric.label))
207
253
  })
208
254
  }),
209
- details.map((detail) => /* @__PURE__ */ jsxs(Row, {
210
- className: "table-fixed",
211
- children: [/* @__PURE__ */ jsx(Column, { children: /* @__PURE__ */ jsx(EmailText, { children: detail.label }) }), /* @__PURE__ */ jsx(Column, {
212
- align: "right",
213
- children: /* @__PURE__ */ jsx(EmailText, { children: detail.value })
214
- })]
255
+ details.map((detail) => /* @__PURE__ */ jsx(EmailDetailRow, {
256
+ label: detail.label,
257
+ value: detail.value
215
258
  }, detail.label)),
216
259
  /* @__PURE__ */ jsx(EmailButton, {
217
260
  href: dashboardUrl,
261
+ className: "mt-4",
218
262
  children: "View your workspace"
263
+ })
264
+ ]
265
+ });
266
+ }
267
+ function VerificationEmail({ theme, variant, head, brand, footer, code, expiresInMinutes, supportUrl }) {
268
+ const layout = {
269
+ theme,
270
+ variant,
271
+ head,
272
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
273
+ footerPlacement: footer.placement
274
+ };
275
+ return /* @__PURE__ */ jsxs(EmailLayout, {
276
+ ...layout,
277
+ preview: `${code} is your verification code`,
278
+ children: [
279
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
280
+ brand,
281
+ colorScheme: theme.colorScheme,
282
+ align: "center"
283
+ }),
284
+ /* @__PURE__ */ jsx(EmailHeading, {
285
+ size: "heading-2",
286
+ align: "center",
287
+ children: "Confirm your email address"
288
+ }),
289
+ /* @__PURE__ */ jsx(EmailText, {
290
+ align: "center",
291
+ children: "Enter this code to finish signing in. It works once, and only for this device."
292
+ }),
293
+ /* @__PURE__ */ jsx(EmailOneTimeCode, { children: code }),
294
+ /* @__PURE__ */ jsxs(EmailCaption, {
295
+ align: "center",
296
+ className: "mb-6",
297
+ children: [
298
+ "The code expires in ",
299
+ expiresInMinutes,
300
+ " minutes."
301
+ ]
302
+ }),
303
+ /* @__PURE__ */ jsxs(EmailText, {
304
+ align: "center",
305
+ className: "mb-0",
306
+ children: [
307
+ "Didn’t ask for this code? Ignore this email, or ",
308
+ /* @__PURE__ */ jsx(EmailLink, {
309
+ href: supportUrl,
310
+ children: "tell our team"
311
+ }),
312
+ "."
313
+ ]
314
+ })
315
+ ]
316
+ });
317
+ }
318
+ function ReceiptEmail({ theme, variant, head, brand, footer, orderNumber, orderDate, lines, total, paymentMethod, invoiceUrl }) {
319
+ const layout = {
320
+ theme,
321
+ variant,
322
+ head,
323
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
324
+ footerPlacement: footer.placement
325
+ };
326
+ return /* @__PURE__ */ jsxs(EmailLayout, {
327
+ ...layout,
328
+ preview: `Receipt ${orderNumber} · ${total}`,
329
+ children: [
330
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
331
+ brand,
332
+ colorScheme: theme.colorScheme
333
+ }),
334
+ /* @__PURE__ */ jsx(EmailCaption, {
335
+ className: "mb-6",
336
+ children: "RECEIPT"
337
+ }),
338
+ /* @__PURE__ */ jsx(EmailHeading, {
339
+ size: "heading-3",
340
+ children: "Thanks for your order."
341
+ }),
342
+ /* @__PURE__ */ jsxs(EmailText, { children: [
343
+ "Order ",
344
+ /* @__PURE__ */ jsx(EmailInlineCode, { children: orderNumber }),
345
+ " was confirmed on ",
346
+ orderDate,
347
+ ". Keep this receipt for your records."
348
+ ] }),
349
+ /* @__PURE__ */ jsxs(EmailPanel, { children: [
350
+ lines.map((line) => /* @__PURE__ */ jsx(EmailDetailRow, {
351
+ label: line.label,
352
+ value: line.value
353
+ }, line.label)),
354
+ /* @__PURE__ */ jsx(EmailDivider, { className: "my-3" }),
355
+ /* @__PURE__ */ jsx(EmailDetailRow, {
356
+ label: "Total",
357
+ value: total,
358
+ emphasis: true
359
+ })
360
+ ] }),
361
+ /* @__PURE__ */ jsxs(EmailCaption, {
362
+ className: "mb-6",
363
+ children: [
364
+ "Paid with ",
365
+ paymentMethod,
366
+ "."
367
+ ]
219
368
  }),
220
- /* @__PURE__ */ jsx(EmailFooter, {
369
+ /* @__PURE__ */ jsx(EmailButton, {
370
+ href: invoiceUrl,
371
+ children: "View invoice"
372
+ })
373
+ ]
374
+ });
375
+ }
376
+ function ReleaseNotesEmail({ theme, variant, head, brand, browserUrl, footer, version, summary, sections, migration, changelogUrl }) {
377
+ const layout = {
378
+ theme,
379
+ variant,
380
+ head,
381
+ footer: /* @__PURE__ */ jsx(EmailBrandFooter, { footer }),
382
+ footerPlacement: footer.placement
383
+ };
384
+ return /* @__PURE__ */ jsxs(EmailLayout, {
385
+ ...layout,
386
+ preview: `What shipped in ${version}`,
387
+ children: [
388
+ /* @__PURE__ */ jsx(EmailBrandHeader, {
221
389
  brand,
222
- children: footer
390
+ browserUrl,
391
+ colorScheme: theme.colorScheme
392
+ }),
393
+ /* @__PURE__ */ jsxs(EmailCaption, {
394
+ className: "mb-6",
395
+ children: ["RELEASE ", version]
396
+ }),
397
+ /* @__PURE__ */ jsx(EmailHeading, {
398
+ size: "heading-2",
399
+ children: "What shipped this month."
400
+ }),
401
+ /* @__PURE__ */ jsx(EmailText, { children: summary }),
402
+ sections.map((section) => /* @__PURE__ */ jsxs(EmailSection, {
403
+ className: "mb-4",
404
+ children: [/* @__PURE__ */ jsx(EmailHeading, {
405
+ as: "h3",
406
+ children: section.title
407
+ }), /* @__PURE__ */ jsx(EmailBulletList, { items: section.changes })]
408
+ }, section.title)),
409
+ migration ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(EmailMarkdown, {
410
+ theme,
411
+ variant,
412
+ children: migration.notes
413
+ }), /* @__PURE__ */ jsx(EmailCodeBlock, {
414
+ theme,
415
+ language: migration.language,
416
+ code: migration.code
417
+ })] }) : null,
418
+ /* @__PURE__ */ jsx(EmailButton, {
419
+ href: changelogUrl,
420
+ children: "Read the full changelog"
223
421
  })
224
422
  ]
225
423
  });
226
424
  }
227
425
  //#endregion
228
- export { EditorialEmail, InvitationEmail, NewsletterEmail, ProductEmail, SummaryEmail };
426
+ export { EditorialEmail, InvitationEmail, NewsletterEmail, ProductEmail, ReceiptEmail, ReleaseNotesEmail, SummaryEmail, VerificationEmail };
@@ -1,19 +1,23 @@
1
1
  //#region src/email/theme.d.ts
2
2
  declare const emailColors: readonly ["background", "foreground", "card", "card-foreground", "primary", "primary-foreground", "primary-text", "muted", "muted-foreground", "border"];
3
- declare const headingSizes: readonly ["heading-1", "heading-2", "heading-3", "heading-4"];
3
+ declare const titleSizes: readonly ["display", "heading-1", "heading-2", "heading-3", "heading-4"];
4
4
  type EmailColor = (typeof emailColors)[number];
5
- type EmailHeadingSize = (typeof headingSizes)[number];
5
+ type EmailTitleSize = (typeof titleSizes)[number];
6
+ type EmailCodeToken = "foreground" | "comment" | "keyword" | "string" | "function" | "constant" | "punctuation" | "parameter";
6
7
  type EmailTypeStyle = {
7
8
  fontSize: string;
8
9
  lineHeight: string;
9
10
  fontWeight: string;
10
11
  letterSpacing: string;
11
12
  };
13
+ export type EmailColorScheme = "light" | "dark";
12
14
  export type EmailTheme = {
15
+ colorScheme: EmailColorScheme;
13
16
  colors: Record<EmailColor, string>;
14
17
  fonts: {
15
18
  body: string;
16
19
  display: string;
20
+ mono: string;
17
21
  };
18
22
  radii: {
19
23
  control: string;
@@ -27,8 +31,12 @@ export type EmailTheme = {
27
31
  fontSize: string;
28
32
  lineHeight: string;
29
33
  };
30
- text: Record<EmailHeadingSize | "body" | "caption", EmailTypeStyle>;
34
+ text: Record<EmailTitleSize | "body" | "caption", EmailTypeStyle>;
35
+ code: Record<EmailCodeToken, string>;
31
36
  };
32
- export declare function createEmailTheme(tokens: ReadonlyMap<string, string>, rootFontSize?: number): EmailTheme;
33
- export declare function emailThemeFromCss(cssSources: string[], mode?: "light" | "dark", rootFontSize?: number): EmailTheme;
37
+ export declare function createEmailTheme(tokens: ReadonlyMap<string, string>, { rootFontSize, colorScheme }?: {
38
+ rootFontSize?: number;
39
+ colorScheme?: EmailColorScheme;
40
+ }): EmailTheme;
41
+ export declare function emailThemeFromCss(cssSources: string[], mode?: EmailColorScheme, rootFontSize?: number): EmailTheme;
34
42
  //#endregion
@@ -25,7 +25,7 @@ function numericStyle(name, tokens, fallback) {
25
25
  if (!/^\d*\.?\d+(px|em)?$/.test(value)) throw new Error(`Email theme: unsupported ${name}: ${value}.`);
26
26
  return value;
27
27
  }
28
- function createEmailTheme(tokens, rootFontSize = 16) {
28
+ function createEmailTheme(tokens, { rootFontSize = 16, colorScheme = "light" } = {}) {
29
29
  if (!Number.isFinite(rootFontSize) || rootFontSize <= 0) throw new Error("Email theme: rootFontSize must be a positive pixel value.");
30
30
  function lengthPixels(name, allowZero = false) {
31
31
  return emailLengthPixels(name, tokenValue(name, tokens), rootFontSize, allowZero);
@@ -43,11 +43,17 @@ function createEmailTheme(tokens, rootFontSize = 16) {
43
43
  if (background.alpha !== 1) throw new Error("Email theme: --background must be opaque.");
44
44
  const card = composite(color("card"), background);
45
45
  const primary = composite(color("primary"), card);
46
+ const muted = composite(color("muted"), card);
46
47
  function opaqueColor(name, surface = card) {
47
48
  const result = composite(color(name), surface);
48
49
  return `rgb(${Math.round(result.r)}, ${Math.round(result.g)}, ${Math.round(result.b)})`;
49
50
  }
50
- function heading(name) {
51
+ function codeColor(token) {
52
+ const syntaxToken = token === "foreground" ? "code-foreground" : `code-token-${token}`;
53
+ const withoutCodeCss = token === "comment" ? "muted-foreground" : "card-foreground";
54
+ return opaqueColor(tokens.has(`--${syntaxToken}`) ? syntaxToken : withoutCodeCss, muted);
55
+ }
56
+ function title(name) {
51
57
  const spacing = tokenValue(`--text-${name}--letter-spacing`, tokens, "0");
52
58
  if (!/^-?\d*\.?\d+(px|em)?$/.test(spacing)) throw new Error(`Email theme: unsupported ${name} letter spacing: ${spacing}.`);
53
59
  return {
@@ -58,6 +64,7 @@ function createEmailTheme(tokens, rootFontSize = 16) {
58
64
  };
59
65
  }
60
66
  return {
67
+ colorScheme,
61
68
  colors: {
62
69
  background: opaqueColor("background", background),
63
70
  foreground: opaqueColor("foreground", background),
@@ -72,7 +79,8 @@ function createEmailTheme(tokens, rootFontSize = 16) {
72
79
  },
73
80
  fonts: {
74
81
  body: tokenValue("--font-body", tokens),
75
- display: tokenValue("--font-display", tokens)
82
+ display: tokenValue("--font-display", tokens),
83
+ mono: tokenValue("--font-mono", tokens)
76
84
  },
77
85
  radii: {
78
86
  control: `${lengthPixels("--radius-control", true)}px`,
@@ -99,15 +107,29 @@ function createEmailTheme(tokens, rootFontSize = 16) {
99
107
  fontWeight: "400",
100
108
  letterSpacing: "0"
101
109
  },
102
- "heading-1": heading("heading-1"),
103
- "heading-2": heading("heading-2"),
104
- "heading-3": heading("heading-3"),
105
- "heading-4": heading("heading-4")
110
+ display: title("display"),
111
+ "heading-1": title("heading-1"),
112
+ "heading-2": title("heading-2"),
113
+ "heading-3": title("heading-3"),
114
+ "heading-4": title("heading-4")
115
+ },
116
+ code: {
117
+ foreground: codeColor("foreground"),
118
+ comment: codeColor("comment"),
119
+ keyword: codeColor("keyword"),
120
+ string: codeColor("string"),
121
+ function: codeColor("function"),
122
+ constant: codeColor("constant"),
123
+ punctuation: codeColor("punctuation"),
124
+ parameter: codeColor("parameter")
106
125
  }
107
126
  };
108
127
  }
109
128
  function emailThemeFromCss(cssSources, mode = "light", rootFontSize = 16) {
110
- return createEmailTheme(tokenMaps(cssSources)[mode], rootFontSize);
129
+ return createEmailTheme(tokenMaps(cssSources)[mode], {
130
+ rootFontSize,
131
+ colorScheme: mode
132
+ });
111
133
  }
112
134
  //#endregion
113
135
  export { createEmailTheme, emailThemeFromCss };
@@ -21,6 +21,7 @@ export type ChatMessageContext = {
21
21
  isTool: boolean;
22
22
  isCompact: boolean;
23
23
  isStreaming: boolean;
24
+ isPending: boolean;
24
25
  isError: boolean;
25
26
  };
26
27
  export declare function useChatMessage({ from, state, density }: Pick<ChatMessageProps, "from" | "state" | "density">): ChatMessageContext;
@@ -10,6 +10,7 @@ function getChatMessageContext({ from, state, density }) {
10
10
  isTool: from === "tool",
11
11
  isCompact: density === "compact",
12
12
  isStreaming: state === "streaming",
13
+ isPending: state === "pending",
13
14
  isError: state === "error"
14
15
  };
15
16
  }
@@ -0,0 +1,8 @@
1
+ //#region src/hooks/use-chat-thread-scroll.d.ts
2
+ export declare function useChatThreadScroll(): {
3
+ viewportRef: import("react").RefObject<HTMLDivElement | null>;
4
+ contentRef: import("react").RefObject<HTMLDivElement | null>;
5
+ atBottom: boolean;
6
+ scrollToBottom: (behavior?: ScrollBehavior) => void;
7
+ };
8
+ //#endregion