@cloudgrid-io/ui 0.31.3 → 0.31.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 (109) hide show
  1. package/README.md +32 -0
  2. package/dist/badge/brand.d.ts +8 -0
  3. package/dist/badge/brand.d.ts.map +1 -0
  4. package/dist/badge/brand.js +22 -0
  5. package/dist/badge/brand.js.map +1 -0
  6. package/dist/badge/css-base.d.ts +25 -0
  7. package/dist/badge/css-base.d.ts.map +1 -0
  8. package/dist/badge/css-base.js +103 -0
  9. package/dist/badge/css-base.js.map +1 -0
  10. package/dist/badge/css-owner.d.ts +7 -0
  11. package/dist/badge/css-owner.d.ts.map +1 -0
  12. package/dist/badge/css-owner.js +128 -0
  13. package/dist/badge/css-owner.js.map +1 -0
  14. package/dist/badge/css-visitor.d.ts +7 -0
  15. package/dist/badge/css-visitor.d.ts.map +1 -0
  16. package/dist/badge/css-visitor.js +75 -0
  17. package/dist/badge/css-visitor.js.map +1 -0
  18. package/dist/badge/html.d.ts +26 -0
  19. package/dist/badge/html.d.ts.map +1 -0
  20. package/dist/badge/html.js +55 -0
  21. package/dist/badge/html.js.map +1 -0
  22. package/dist/badge/index.d.ts +43 -0
  23. package/dist/badge/index.d.ts.map +1 -0
  24. package/dist/badge/index.js +46 -0
  25. package/dist/badge/index.js.map +1 -0
  26. package/dist/badge/marks.d.ts +45 -0
  27. package/dist/badge/marks.d.ts.map +1 -0
  28. package/dist/badge/marks.js +126 -0
  29. package/dist/badge/marks.js.map +1 -0
  30. package/dist/badge/owner.d.ts +213 -0
  31. package/dist/badge/owner.d.ts.map +1 -0
  32. package/dist/badge/owner.js +309 -0
  33. package/dist/badge/owner.js.map +1 -0
  34. package/dist/badge/palette.d.ts +23 -0
  35. package/dist/badge/palette.d.ts.map +1 -0
  36. package/dist/badge/palette.js +86 -0
  37. package/dist/badge/palette.js.map +1 -0
  38. package/dist/badge/root.d.ts +24 -0
  39. package/dist/badge/root.d.ts.map +1 -0
  40. package/dist/badge/root.js +11 -0
  41. package/dist/badge/root.js.map +1 -0
  42. package/dist/badge/shared.d.ts +56 -0
  43. package/dist/badge/shared.d.ts.map +1 -0
  44. package/dist/badge/shared.js +53 -0
  45. package/dist/badge/shared.js.map +1 -0
  46. package/dist/badge/visitor.d.ts +96 -0
  47. package/dist/badge/visitor.d.ts.map +1 -0
  48. package/dist/badge/visitor.js +119 -0
  49. package/dist/badge/visitor.js.map +1 -0
  50. package/dist/blocks/confirm-delete-dialog.d.ts +81 -0
  51. package/dist/blocks/confirm-delete-dialog.d.ts.map +1 -0
  52. package/dist/blocks/confirm-delete-dialog.js +89 -0
  53. package/dist/blocks/confirm-delete-dialog.js.map +1 -0
  54. package/dist/blocks/entity-status.d.ts +44 -1
  55. package/dist/blocks/entity-status.d.ts.map +1 -1
  56. package/dist/blocks/entity-status.js +26 -1
  57. package/dist/blocks/entity-status.js.map +1 -1
  58. package/dist/blocks/expiry-notice.d.ts +86 -0
  59. package/dist/blocks/expiry-notice.d.ts.map +1 -0
  60. package/dist/blocks/expiry-notice.js +81 -0
  61. package/dist/blocks/expiry-notice.js.map +1 -0
  62. package/dist/blocks/icons.d.ts +22 -0
  63. package/dist/blocks/icons.d.ts.map +1 -1
  64. package/dist/blocks/icons.js +22 -0
  65. package/dist/blocks/icons.js.map +1 -1
  66. package/dist/blocks/notification-row.d.ts +88 -0
  67. package/dist/blocks/notification-row.d.ts.map +1 -0
  68. package/dist/blocks/notification-row.js +32 -0
  69. package/dist/blocks/notification-row.js.map +1 -0
  70. package/dist/blocks/phosphor-marks.d.ts +10 -0
  71. package/dist/blocks/phosphor-marks.d.ts.map +1 -1
  72. package/dist/blocks/phosphor-marks.js +15 -0
  73. package/dist/blocks/phosphor-marks.js.map +1 -1
  74. package/dist/blocks/shelf.d.ts +384 -0
  75. package/dist/blocks/shelf.d.ts.map +1 -0
  76. package/dist/blocks/shelf.js +489 -0
  77. package/dist/blocks/shelf.js.map +1 -0
  78. package/dist/brand/badge/manrope-latin-wght-normal.woff2 +0 -0
  79. package/dist/brand/badge/space-grotesk-latin-wght-normal.woff2 +0 -0
  80. package/dist/brand/email/headline-activity.png +0 -0
  81. package/dist/brand/email/headline-expired.png +0 -0
  82. package/dist/brand/email/headline-expires-tomorrow.png +0 -0
  83. package/dist/brand/email/headline-expiring-soon.png +0 -0
  84. package/dist/brand/email/headline-invited.png +0 -0
  85. package/dist/brand/email/headline-sign-in-code.png +0 -0
  86. package/dist/brand/email/mesh.png +0 -0
  87. package/dist/brand/email/wordmark.png +0 -0
  88. package/dist/email/assets.d.ts +50 -0
  89. package/dist/email/assets.d.ts.map +1 -0
  90. package/dist/email/assets.js +16 -0
  91. package/dist/email/assets.js.map +1 -0
  92. package/dist/email/index.d.ts +204 -0
  93. package/dist/email/index.d.ts.map +1 -0
  94. package/dist/email/index.js +429 -0
  95. package/dist/email/index.js.map +1 -0
  96. package/dist/email/palette.d.ts +40 -0
  97. package/dist/email/palette.d.ts.map +1 -0
  98. package/dist/email/palette.js +44 -0
  99. package/dist/email/palette.js.map +1 -0
  100. package/dist/index.d.ts +4 -0
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +4 -0
  103. package/dist/index.js.map +1 -1
  104. package/dist/shadcn.css +41 -0
  105. package/dist/ui/dropdown-menu.d.ts +8 -1
  106. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  107. package/dist/ui/dropdown-menu.js +9 -2
  108. package/dist/ui/dropdown-menu.js.map +1 -1
  109. package/package.json +17 -1
@@ -0,0 +1,429 @@
1
+ /**
2
+ * THE CLOUDGRID EMAIL LAYOUT (ui#295). Content in, `{ html, text }` out.
3
+ *
4
+ * One layout for every email CloudGrid sends: the sign-in code, invites,
5
+ * reactions, activity and the expiry warnings. The platform calls it; the
6
+ * styleguide previews its real output (`/gallery/email`), so what a reviewer
7
+ * sees is the string the platform will send.
8
+ *
9
+ * ```ts
10
+ * import { renderEmail } from "@cloudgrid-io/ui/email"
11
+ * const { html, text } = renderEmail({ headline: "expiring-soon", title, points, action, note, footer })
12
+ * ```
13
+ *
14
+ * ## It speaks the library's language (founder revision, 2026-10-11)
15
+ *
16
+ * The first cut was a generic transactional email, and the founder rejected it:
17
+ * "it doesn't use our logo or our language". So every element here is taken
18
+ * from a library element and its tokens, the way the Console's sign-in and the
19
+ * `EmptyCreations` block draw them:
20
+ *
21
+ * the logo `Logo`'s own paths, as a PNG (wordmark.png), top left
22
+ * the headline Tanker, uppercase, brand purple, at the sign-in's size
23
+ * ("READY TO PLUG IN?"), as a PNG per headline, its words as
24
+ * styled alt text
25
+ * the body Space Grotesk where the client loads web fonts, else the
26
+ * system stack; the title is the first line under the
27
+ * headline, at the sign-in subline's 19px
28
+ * the button the `cta` button as `EmptyCreations` sets it: teal, ink
29
+ * label in Manrope bold, 40px tall, 16px corners, 20px sides
30
+ * an item the entity card: the identity media (field colour, the grid,
31
+ * the monogram tile), name and kind, and the expiring status
32
+ * pill exactly as `EntityExpiryStatus` draws it
33
+ * the frame lavender ground, the white container at the library's
34
+ * container radius, centred like the sign-in and the empty
35
+ * state, and the sign-in's footer
36
+ *
37
+ * ## No React, no dependencies
38
+ *
39
+ * The API runs this, not a browser. The module imports only its two generated
40
+ * siblings, `./palette.js` (colours and shape, from tokens.css at build) and
41
+ * `./assets.js` (the image manifest, from scripts/generate-email-assets.mjs).
42
+ * `test/email.test.mjs` asserts that.
43
+ *
44
+ * ## Email clients
45
+ *
46
+ * Outlook for Windows renders with Word: no flexbox, no `var()`, no rounded
47
+ * corners, no background images on a cell without VML. Gmail strips `<link>`
48
+ * and every custom property, and loads no web font. So: nested tables, inline
49
+ * styles, colours as hex and again as `bgcolor`, a fixed 560px column inside an
50
+ * Outlook-only table, and pictures for the two things a system font cannot be
51
+ * (the wordmark and the Tanker headline). Outlook draws the corners square and
52
+ * the identity field flat; everything else holds.
53
+ *
54
+ * ## Images off
55
+ *
56
+ * The wordmark and headline carry alt text styled as what they show (purple,
57
+ * bold, uppercase for a headline), so an inbox that blocks images still shows a
58
+ * purple "EXPIRING SOON" where the picture was. The identity media keeps its
59
+ * field colour without the grid; the monogram tile is not an image at all.
60
+ *
61
+ * ## Assets: the sender names the host, or there are none
62
+ *
63
+ * The library never chooses where a recipient's mail client fetches anything
64
+ * from (Gilad's review of ui#296: a third-party host sees every recipient's IP
65
+ * and open time, is blocked on some networks, and costs deliverability).
66
+ *
67
+ * - `assetBaseUrl` set: the wordmark, the headline and the grid tile load from
68
+ * there. The sender serves this package's `dist/brand/email/*` from its own
69
+ * domain and passes that base.
70
+ * - `assetBaseUrl` absent: the email is image-free for every client. The
71
+ * wordmark and headline are live text, the treatment Outlook gets anyway,
72
+ * and the identity field is plain colour. Nothing is requested from any
73
+ * host the caller did not name.
74
+ * - `webFontsUrl` likewise: the brand faces load only from a stylesheet the
75
+ * caller names; without it the system stack renders.
76
+ * - An item's `imageUrl` is the caller's own URL and is used as given.
77
+ *
78
+ * ## Escaping
79
+ *
80
+ * Every string the caller passes is text, never HTML: `&`, `<`, `>`, `"` and
81
+ * `'` are escaped wherever they land. A URL is percent-encoded where it is not
82
+ * already, then attribute-escaped. A URL with any scheme other than `http`,
83
+ * `https` or `mailto` (a `javascript:` link, say) is replaced by `#`.
84
+ */
85
+ import { EMAIL_HEADLINES, EMAIL_MESH, EMAIL_WORDMARK } from "./assets.js";
86
+ import { EMAIL_PALETTE as C, EMAIL_SHAPE as S } from "./palette.js";
87
+ export { EMAIL_HEADLINES };
88
+ /**
89
+ * The Google Fonts stylesheet for the two faces the email names, for a sender
90
+ * that chooses to accept Google as a host. Passed as `webFontsUrl`; never used
91
+ * unless passed.
92
+ */
93
+ export const GOOGLE_FONTS_EMAIL_CSS = "https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Manrope:wght@500;600;700&display=swap";
94
+ // ---- text and URL safety ----------------------------------------------------
95
+ const ESCAPES = {
96
+ "&": "&amp;",
97
+ "<": "&lt;",
98
+ ">": "&gt;",
99
+ '"': "&quot;",
100
+ "'": "&#39;",
101
+ };
102
+ /** Text to HTML text, safe in an element body and in a quoted attribute. */
103
+ export function escapeHtml(value) {
104
+ return String(value).replace(/[&<>"']/g, (c) => ESCAPES[c] ?? c);
105
+ }
106
+ /** The characters a URL may carry as they are (RFC 3986 reserved and unreserved). */
107
+ const URL_SAFE = /[A-Za-z0-9\-._~:/?#[\]@!$&'()*+,;=%]/;
108
+ const ALLOWED_SCHEMES = new Set(["http", "https", "mailto"]);
109
+ /**
110
+ * A URL, percent-encoded where it is not already, with any scheme other than
111
+ * http, https or mailto replaced by `#`. Returns the URL for a text body; pass
112
+ * the result through `escapeHtml` before putting it in an attribute.
113
+ */
114
+ export function safeUrl(url) {
115
+ const trimmed = String(url).trim();
116
+ // Browsers drop tabs, newlines and control characters before reading a
117
+ // scheme, so "java\nscript:" is javascript:. Read the scheme the same way.
118
+ const probe = trimmed.replace(/[\u0000- \u007f]/g, "");
119
+ const scheme = probe.match(/^([a-z][a-z0-9+.-]*):/i);
120
+ if (scheme && !ALLOWED_SCHEMES.has(scheme[1].toLowerCase()))
121
+ return "#";
122
+ // A `%` that does not start an escape is a literal percent sign.
123
+ const percent = trimmed.replace(/%(?![0-9A-Fa-f]{2})/g, "%25");
124
+ let out = "";
125
+ for (const ch of percent) {
126
+ if (URL_SAFE.test(ch)) {
127
+ out += ch;
128
+ continue;
129
+ }
130
+ try {
131
+ out += encodeURIComponent(ch);
132
+ }
133
+ catch {
134
+ // A lone surrogate cannot be encoded. U+FFFD, as a browser would.
135
+ out += "%EF%BF%BD";
136
+ }
137
+ }
138
+ return out;
139
+ }
140
+ const attrUrl = (url) => escapeHtml(safeUrl(url));
141
+ // ---- Outlook ------------------------------------------------------------------
142
+ //
143
+ // Outlook for Windows blocks images by default, so it never gets one: every
144
+ // picture has an Outlook twin made of live text and table cells, and the two are
145
+ // fenced with Microsoft's conditional comments. Every other client reads the
146
+ // `!mso` branch (its comment markers are plain comments to them) and never sees
147
+ // the `mso` one.
148
+ /** Only Outlook for Windows renders this. */
149
+ const mso = (html) => `<!--[if mso]>${html}<![endif]-->`;
150
+ /** Everyone except Outlook for Windows renders this. */
151
+ const notMso = (html) => `<!--[if !mso]><!-->${html}<!--<![endif]-->`;
152
+ /** A heavy system face for live-text stand-ins, where Tanker cannot reach. */
153
+ const HEAVY = "'Arial Black', 'Helvetica Neue', Arial, sans-serif";
154
+ /** The wordmark's stand-in face. */
155
+ const WORDMARK_FACE = "Arial, Helvetica, sans-serif";
156
+ /**
157
+ * A size for a headline's alt text that fits the image's own width in the heavy
158
+ * face, so a blocked headline sets as one designed line, not a clipped one.
159
+ * Arial Black's capitals average about 0.72em.
160
+ */
161
+ function altSize(text, width) {
162
+ return Math.max(18, Math.min(30, Math.floor(width / (text.length * 0.72))));
163
+ }
164
+ // ---- the shape --------------------------------------------------------------
165
+ const BODY = S.fontBody;
166
+ const UI = S.fontUi;
167
+ /** Every layout table: no spacing, no border, announced as nothing. */
168
+ const TABLE = 'role="presentation" cellpadding="0" cellspacing="0" border="0"';
169
+ /**
170
+ * The width an item's picture is drawn at: the 560 column, less the container's
171
+ * 1px border and 40px padding a side, less the card's own 1px border.
172
+ */
173
+ export const EMAIL_ITEM_IMAGE_WIDTH = 560 - 2 * (1 + 40) - 2 * 1;
174
+ /** How tall a blocked item picture's alt-text strip is. */
175
+ const ALT_STRIP = 64;
176
+ const TILE = { page: C.tilePage, app: C.tileApp, agent: C.tileAgent };
177
+ const FIELD = { page: C.fieldPage, app: C.fieldApp, agent: C.fieldAgent };
178
+ const STATUS = {
179
+ soon: { fill: C.soonFill, border: C.soonBorder, text: C.soon, dot: C.soonDot },
180
+ urgent: { fill: C.urgentFill, border: C.urgentBorder, text: C.urgent, dot: C.urgentDot },
181
+ };
182
+ /** The caller's web-font stylesheet, if it named one. Gmail drops the tag either way. */
183
+ const fontLink = (url) => (url ? `<link rel="stylesheet" href="${attrUrl(url)}">` : "");
184
+ function assetUrl(base, file) {
185
+ return attrUrl(`${base.endsWith("/") ? base : `${base}/`}${file}`);
186
+ }
187
+ /** The `cta` button, as EmptyCreations sets it. `small` is the per-item size. */
188
+ function button(link, small = false) {
189
+ const pad = small ? "6px 16px" : "10px 20px";
190
+ const size = small ? 14 : 15;
191
+ return (`<table ${TABLE} style="border-collapse:separate;"><tr>` +
192
+ `<td align="center" bgcolor="${C.button}" style="background-color:${C.button};border-radius:${S.radiusButton}px;mso-padding-alt:${pad};">` +
193
+ `<a href="${attrUrl(link.url)}" target="_blank" rel="noopener" style="display:inline-block;padding:${pad};font-family:${UI};font-size:${size}px;font-weight:700;line-height:20px;color:${C.onButton};text-decoration:none;border-radius:${S.radiusButton}px;white-space:nowrap;">` +
194
+ `${escapeHtml(link.label)}</a></td></tr></table>`);
195
+ }
196
+ /** The `EntityExpiryStatus` pill: fill, border, dot and the word in the strong tone. */
197
+ function statusPill(status) {
198
+ const t = STATUS[status.tone] ?? STATUS.soon;
199
+ return (`<table ${TABLE} style="border-collapse:separate;"><tr>` +
200
+ `<td bgcolor="${t.fill}" style="background-color:${t.fill};border:1px solid ${t.border};border-radius:999px;padding:2px 10px;font-family:${BODY};font-size:13px;line-height:19px;font-weight:500;color:${t.text};white-space:nowrap;">` +
201
+ `<span style="display:inline-block;width:6px;height:6px;border-radius:999px;background-color:${t.dot};vertical-align:middle;margin:0 6px 2px 0;font-size:0;line-height:0;">&nbsp;</span>` +
202
+ `${escapeHtml(status.label)}</td></tr></table>`);
203
+ }
204
+ function monogram(value) {
205
+ const chars = [...String(value).trim()];
206
+ return chars.length === 0 ? "?" : chars.slice(0, 2).join("");
207
+ }
208
+ /** One item, as an entity card: the identity media, then name, kind and status. */
209
+ function item(it, base) {
210
+ const tone = it.tone ?? "app";
211
+ const status = it.status ?? it.badge;
212
+ // Inside url('...') too, so an apostrophe is percent-encoded rather than escaped.
213
+ // No base, no grid: the field is plain colour and nothing is fetched.
214
+ const mesh = base ? assetUrl(base, EMAIL_MESH.file).replace(/&#39;/g, "%27") : undefined;
215
+ const r = S.radiusCard;
216
+ // The tinted grid is the media area's ground either way: behind the picture,
217
+ // so a blocked image still sits on the entity's colour, and on its own with
218
+ // the monogram tile when there is no picture.
219
+ const ground = `bgcolor="${FIELD[tone]}" ${mesh ? `background="${mesh}" ` : ""}`;
220
+ const groundStyle = `background-color:${FIELD[tone]};` +
221
+ (mesh
222
+ ? `background-image:url('${mesh}');background-size:${EMAIL_MESH.size}px ${EMAIL_MESH.size}px;background-position:-1px -1px;background-repeat:repeat;`
223
+ : "") +
224
+ `border-radius:${r - 1}px ${r - 1}px 0 0;`;
225
+ const w = EMAIL_ITEM_IMAGE_WIDTH;
226
+ const tile = `<td align="center" valign="middle" height="112" ${ground}style="height:112px;${groundStyle}">` +
227
+ `<table ${TABLE} align="center" style="border-collapse:separate;"><tr>` +
228
+ `<td width="46" height="46" align="center" valign="middle" bgcolor="${TILE[tone]}" style="width:46px;height:46px;background-color:${TILE[tone]};border-radius:${S.radiusTile}px;font-family:${BODY};font-size:20px;line-height:46px;font-weight:700;color:${C.onPrimary};">` +
229
+ `${escapeHtml(monogram(it.monogram))}</td></tr></table></td>`;
230
+ const picture = it.imageUrl
231
+ ? `<td align="center" valign="middle" ${ground}style="${groundStyle}font-size:0;line-height:0;">` +
232
+ // width:100% with no max-width: on a phone the container's padding drops
233
+ // to 20px and the card grows past 476, and the picture must grow with it.
234
+ // No height attribute, so a blocked picture is not an empty 1200:630 box:
235
+ // it collapses to its alt text, the name in the tile's colour, on a
236
+ // ${ALT_STRIP}px strip of the tinted grid.
237
+ `<img src="${attrUrl(it.imageUrl)}" width="${w}" alt="${escapeHtml(it.name)}" ` +
238
+ `style="display:block;width:100%;height:auto;border:0;outline:none;border-radius:${r - 1}px ${r - 1}px 0 0;font-family:${BODY};font-size:16px;line-height:${ALT_STRIP}px;font-weight:700;color:${TILE[tone]};text-align:center;">` +
239
+ `</td>`
240
+ : undefined;
241
+ // Outlook never gets the picture: it blocks images by default, so it gets the tile.
242
+ const media = picture ? `${notMso(`<tr>${picture}</tr>`)}${mso(`<tr>${tile}</tr>`)}` : `<tr>${tile}</tr>`;
243
+ const meta = `<table ${TABLE} width="100%" style="width:100%;"><tr>` +
244
+ `<td valign="middle" style="font-family:${BODY};">` +
245
+ `<div style="font-size:16px;line-height:1.35;font-weight:500;color:${C.text};">${escapeHtml(it.name)}</div>` +
246
+ `<div style="font-size:13px;line-height:1.45;color:${C.textSecondary};">${escapeHtml(it.detail)}</div></td>` +
247
+ (status ? `<td align="right" valign="middle" style="padding-left:12px;">${statusPill(status)}</td>` : "") +
248
+ `</tr></table>` +
249
+ (it.action ? `<table ${TABLE} style="margin-top:14px;"><tr><td>${button(it.action, true)}</td></tr></table>` : "");
250
+ return (`<table ${TABLE} width="100%" bgcolor="${C.card}" style="width:100%;background-color:${C.card};border:1px solid ${C.hairline};border-radius:${r}px;border-collapse:separate;">` +
251
+ media +
252
+ `<tr><td style="padding:14px 16px 16px;">${meta}</td></tr>` +
253
+ `</table>`);
254
+ }
255
+ /** One block of the card, spaced from the one above it. */
256
+ const row = (content, top, align = "center") => `<tr><td align="${align}" style="padding-top:${top}px;text-align:${align};">${content}</td></tr>`;
257
+ function headlineBlock(content, base) {
258
+ const h = content.headline ? EMAIL_HEADLINES[content.headline] : undefined;
259
+ if (!h) {
260
+ // No headline: the title is the heading, in the body face.
261
+ return `<h1 style="margin:0;font-family:${BODY};font-size:24px;line-height:1.25;font-weight:700;color:${C.text};">${escapeHtml(content.title)}</h1>`;
262
+ }
263
+ const words = escapeHtml(h.text);
264
+ const live = `<span style="display:block;font-family:${HEAVY};font-size:34px;line-height:${h.height}px;font-weight:900;letter-spacing:1px;text-transform:uppercase;color:${C.primary};text-align:center;">${words}</span>`;
265
+ // No base: live text for everyone, the treatment Outlook gets.
266
+ if (!base)
267
+ return `<h1 style="margin:0;font-size:0;line-height:0;">${live}</h1>`;
268
+ return (`<h1 style="margin:0;font-size:0;line-height:0;">` +
269
+ // The picture, its alt text styled as a heading for a client that blocks it.
270
+ // No height attribute: a blocked image then takes the alt text's height
271
+ // rather than holding an empty box.
272
+ notMso(`<img src="${assetUrl(base, h.file)}" width="${h.width}" alt="${words}" ` +
273
+ `style="display:block;margin:0 auto;border:0;outline:none;max-width:100%;height:auto;font-family:${HEAVY};font-size:${altSize(h.text, h.width)}px;line-height:${h.height}px;font-weight:900;letter-spacing:0.02em;text-transform:uppercase;color:${C.primary};text-align:center;">`) +
274
+ // Outlook: the same words as live text, sized like the picture.
275
+ mso(live) +
276
+ `</h1>`);
277
+ }
278
+ /**
279
+ * The points: a small table centred in the card, one row per fact, a brand
280
+ * purple bullet and the words left-aligned beside it. The bullet is a text
281
+ * character rather than a drawn dot, so Outlook (which draws no inline-block
282
+ * box) shows it too; the same markup serves every branch.
283
+ */
284
+ function pointsList(points) {
285
+ const rows = points
286
+ .map((p) => `<tr>` +
287
+ `<td valign="top" style="padding:3px 10px 3px 0;font-family:${BODY};font-size:15px;line-height:22px;font-weight:700;color:${C.primary};">•</td>` +
288
+ `<td valign="top" align="left" style="padding:3px 0;font-family:${BODY};font-size:15px;line-height:22px;color:${C.text};text-align:left;">${escapeHtml(p)}</td>` +
289
+ `</tr>`)
290
+ .join("");
291
+ return `<table ${TABLE} align="center" style="margin:0 auto;">${rows}</table>`;
292
+ }
293
+ function cardRows(content, base) {
294
+ const rows = [row(headlineBlock(content, base), 0)];
295
+ if (content.headline && EMAIL_HEADLINES[content.headline]) {
296
+ rows.push(row(`<p style="margin:0;font-family:${BODY};font-size:19px;line-height:1.46;color:${C.textSecondary};">${escapeHtml(content.title)}</p>`, 10));
297
+ }
298
+ if (content.code) {
299
+ rows.push(row(`<table ${TABLE} width="100%" style="width:100%;border-collapse:separate;"><tr>` +
300
+ `<td align="center" bgcolor="${C.raised}" style="background-color:${C.raised};border-radius:${S.radiusCard}px;padding:18px;font-family:${S.fontMono};font-size:30px;line-height:1;font-weight:600;letter-spacing:0.12em;color:${C.text};">` +
301
+ `${escapeHtml(content.code)}</td></tr></table>`, 24));
302
+ }
303
+ if (content.points?.length)
304
+ rows.push(row(pointsList(content.points), 18));
305
+ (content.lines ?? []).forEach((line, i) => {
306
+ rows.push(row(`<p style="margin:0;font-family:${BODY};font-size:15px;line-height:1.55;color:${C.textSecondary};">${escapeHtml(line)}</p>`, i === 0 ? 16 : 10));
307
+ });
308
+ (content.items ?? []).forEach((it, i) => rows.push(row(item(it, base), i === 0 ? 28 : 16, "left")));
309
+ if (content.action)
310
+ rows.push(row(`<table ${TABLE} align="center"><tr><td>${button(content.action)}</td></tr></table>`, 28));
311
+ if (content.note) {
312
+ rows.push(row(`<p style="margin:0;font-family:${BODY};font-size:13px;line-height:1.46;color:${C.textMuted};">${escapeHtml(content.note)}</p>`, content.action ? 12 : 20));
313
+ }
314
+ if (content.secondary) {
315
+ const { prefix, link } = content.secondary;
316
+ rows.push(row(`<p style="margin:0;font-family:${BODY};font-size:13px;line-height:1.5;color:${C.textSecondary};">${escapeHtml(prefix)} ` +
317
+ `<a href="${attrUrl(link.url)}" target="_blank" rel="noopener" style="color:${C.text};text-decoration:underline;">${escapeHtml(link.label)}</a></p>`, 16));
318
+ }
319
+ return rows.join("");
320
+ }
321
+ /** The sign-in footer's copyright line. */
322
+ function copyright() {
323
+ return `© ${new Date().getUTCFullYear()}. CloudGrid. All Rights Reserved.`;
324
+ }
325
+ function footer(content) {
326
+ const { lines, link } = content.footer;
327
+ const p = (inner, last = false) => `<p style="margin:0 0 ${last ? 0 : 6}px;font-family:${BODY};font-size:13px;line-height:1.46;color:${C.textMuted};text-align:center;">${inner}</p>`;
328
+ const parts = lines.map((l) => p(escapeHtml(l)));
329
+ if (link) {
330
+ parts.push(p(`<a href="${attrUrl(link.url)}" target="_blank" rel="noopener" style="color:${C.text};text-decoration:underline;">${escapeHtml(link.label)}</a>${escapeHtml(link.suffix ?? "")}`));
331
+ }
332
+ parts.push(p(escapeHtml(copyright()), true));
333
+ return parts.join("");
334
+ }
335
+ /**
336
+ * The hidden preview line. The run of zero-width joiners after it stops an inbox
337
+ * filling the rest of the preview with the start of the body.
338
+ */
339
+ function preheader(value) {
340
+ if (!value)
341
+ return "";
342
+ return (`<div style="display:none;max-height:0;max-width:0;overflow:hidden;mso-hide:all;font-size:1px;line-height:1px;color:${C.page};opacity:0;">` +
343
+ `${escapeHtml(value)}${"&zwnj;&nbsp;".repeat(60)}</div>`);
344
+ }
345
+ function renderHtml(content) {
346
+ const base = content.assetBaseUrl || undefined;
347
+ const w = EMAIL_WORDMARK;
348
+ const liveMark = `<span style="font-family:${WORDMARK_FACE};font-size:26px;line-height:${w.height}px;font-weight:700;letter-spacing:-0.5px;color:${C.primary};">cloudgrid</span>`;
349
+ return (`<!doctype html>` +
350
+ `<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">` +
351
+ `<head>` +
352
+ `<meta charset="utf-8">` +
353
+ `<meta name="viewport" content="width=device-width, initial-scale=1">` +
354
+ `<meta name="x-apple-disable-message-reformatting">` +
355
+ `<meta name="format-detection" content="telephone=no, date=no, address=no, email=no">` +
356
+ `<meta name="color-scheme" content="light">` +
357
+ `<meta name="supported-color-schemes" content="light">` +
358
+ `<title>${escapeHtml(content.title)}</title>` +
359
+ fontLink(content.webFontsUrl) +
360
+ `<!--[if mso]><noscript><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml></noscript><![endif]-->` +
361
+ `<style>body{margin:0;padding:0;width:100%!important;-webkit-text-size-adjust:100%;}table{border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;}img{border:0;outline:none;text-decoration:none;-ms-interpolation-mode:bicubic;}@media (max-width:600px){.cg-card{padding:32px 20px!important;}}</style>` +
362
+ `</head>` +
363
+ `<body bgcolor="${C.page}" style="margin:0;padding:0;background-color:${C.page};">` +
364
+ preheader(content.preheader) +
365
+ `<table ${TABLE} width="100%" bgcolor="${C.page}" style="width:100%;background-color:${C.page};"><tr>` +
366
+ `<td align="center" style="padding:32px 16px 40px;">` +
367
+ `<!--[if mso]><table ${TABLE} width="560" align="center"><tr><td><![endif]-->` +
368
+ // separate, not the reset's collapse: a collapsed table draws a rounded
369
+ // cell's border square, which showed as a faint edge behind the corners.
370
+ `<table ${TABLE} width="100%" style="width:100%;max-width:560px;border-collapse:separate;">` +
371
+ // the wordmark, top left
372
+ `<tr><td align="left" style="padding:0 4px 24px;">` +
373
+ // The alt says the name; blocked, it is set lowercase and purple, as the mark reads.
374
+ // No base: the live wordmark for everyone.
375
+ (base
376
+ ? notMso(`<img src="${assetUrl(base, w.file)}" width="${w.width}" alt="${escapeHtml(w.alt)}" ` +
377
+ `style="display:block;border:0;outline:none;width:${w.width}px;height:auto;font-family:${WORDMARK_FACE};font-size:24px;line-height:${w.height}px;font-weight:700;letter-spacing:-0.02em;text-transform:lowercase;color:${C.primary};">`) + mso(liveMark)
378
+ : liveMark) +
379
+ `</td></tr>` +
380
+ // the container
381
+ `<tr><td class="cg-card" bgcolor="${C.card}" style="background-color:${C.card};border:1px solid ${C.hairline};border-radius:${S.radiusContainer}px;padding:44px 40px 40px;">` +
382
+ `<table ${TABLE} width="100%" style="width:100%;">${cardRows(content, base)}</table>` +
383
+ `</td></tr>` +
384
+ // the footer
385
+ `<tr><td align="center" style="padding:24px 16px 0;">${footer(content)}</td></tr>` +
386
+ `</table>` +
387
+ `<!--[if mso]></td></tr></table><![endif]-->` +
388
+ `</td></tr></table>` +
389
+ `</body></html>`);
390
+ }
391
+ /**
392
+ * The plain-text part. Everything the HTML says, in the same order, with every
393
+ * link written out as its URL, so a text-only client loses nothing it can act on.
394
+ */
395
+ function renderText(content) {
396
+ const h = content.headline ? EMAIL_HEADLINES[content.headline] : undefined;
397
+ const out = h ? [h.text, content.title] : [content.title];
398
+ if (content.code)
399
+ out.push(content.code);
400
+ if (content.points?.length)
401
+ out.push(content.points.map((p) => `- ${p}`).join("\n"));
402
+ out.push(...(content.lines ?? []));
403
+ for (const it of content.items ?? []) {
404
+ const status = it.status ?? it.badge;
405
+ const lines = [status ? `${it.name} (${status.label})` : it.name, it.detail];
406
+ if (it.action)
407
+ lines.push(`${it.action.label}: ${safeUrl(it.action.url)}`);
408
+ out.push(lines.join("\n"));
409
+ }
410
+ if (content.action)
411
+ out.push(`${content.action.label}: ${safeUrl(content.action.url)}`);
412
+ if (content.note)
413
+ out.push(content.note);
414
+ if (content.secondary) {
415
+ out.push(`${content.secondary.prefix} ${safeUrl(content.secondary.link.url)}`);
416
+ }
417
+ const foot = [...content.footer.lines];
418
+ const link = content.footer.link;
419
+ if (link)
420
+ foot.push(`${link.label}${link.suffix ?? ""}\n${safeUrl(link.url)}`);
421
+ foot.push(copyright());
422
+ out.push(`--\n${foot.join("\n")}`);
423
+ return `${out.join("\n\n")}\n`;
424
+ }
425
+ /** Render one email. Pure: the same content always gives the same strings (within a year). */
426
+ export function renderEmail(content) {
427
+ return { html: renderHtml(content), text: renderText(content) };
428
+ }
429
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/email/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export declare const EMAIL_PALETTE: {
2
+ readonly page: "#f2f1f7";
3
+ readonly card: "#ffffff";
4
+ readonly raised: "#f4f6f8";
5
+ readonly hairline: "#e6e8ea";
6
+ readonly text: "#222222";
7
+ readonly textSecondary: "#595959";
8
+ readonly textMuted: "#6a6a6a";
9
+ readonly primary: "#5a47f0";
10
+ readonly onPrimary: "#ffffff";
11
+ readonly button: "#60e9f0";
12
+ readonly onButton: "#222222";
13
+ readonly soon: "#7a3d0a";
14
+ readonly urgent: "#c42828";
15
+ readonly soonFill: "#fdf3e0";
16
+ readonly soonBorder: "#fedf89";
17
+ readonly soonDot: "#b0662a";
18
+ readonly urgentFill: "#fceded";
19
+ readonly urgentBorder: "#ffd3cd";
20
+ readonly urgentDot: "#e53935";
21
+ readonly tilePage: "#3d7a7d";
22
+ readonly tileApp: "#5a47f0";
23
+ readonly tileAgent: "#637541";
24
+ readonly fieldPage: "#e6fbfd";
25
+ readonly fieldApp: "#ebe9fd";
26
+ readonly fieldAgent: "#f3fae7";
27
+ };
28
+ export type EmailPalette = typeof EMAIL_PALETTE;
29
+ export declare const EMAIL_SHAPE: {
30
+ readonly radiusContainer: 20;
31
+ readonly radiusButton: 16;
32
+ readonly radiusCard: 14;
33
+ readonly radiusTile: 12;
34
+ readonly fontBody: "'Space Grotesk Variable', 'Space Grotesk', 'Manrope Variable', 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
35
+ readonly fontUi: "'Manrope Variable', 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
36
+ readonly fontDisplay: "'Tanker', 'Manrope Variable', 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
37
+ readonly fontMono: "'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace";
38
+ readonly displayTracking: "0.012em";
39
+ };
40
+ //# sourceMappingURL=palette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../../src/email/palette.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BhB,CAAA;AAEV,MAAM,MAAM,YAAY,GAAG,OAAO,aAAa,CAAA;AAE/C,eAAO,MAAM,WAAW;;;;;;;;;;CAUd,CAAA"}
@@ -0,0 +1,44 @@
1
+ // GENERATED by scripts/build-email-palette.mjs from src/tokens.css. Do not edit.
2
+ //
3
+ // Email clients cannot read CSS custom properties, so renderEmail inlines these
4
+ // hex values. Each is the resolved value of the token named beside it, at :root.
5
+ // Retune the token and rebuild; this file follows.
6
+ export const EMAIL_PALETTE = {
7
+ page: "#f2f1f7", // --cg-surface-page-alt
8
+ card: "#ffffff", // --cg-surface-card
9
+ raised: "#f4f6f8", // --cg-surface-raised
10
+ hairline: "#e6e8ea", // --cg-border-hairline
11
+ text: "#222222", // --cg-text-primary
12
+ textSecondary: "#595959", // --cg-text-secondary
13
+ textMuted: "#6a6a6a", // --cg-text-muted-strong
14
+ primary: "#5a47f0", // --cg-primary
15
+ onPrimary: "#ffffff", // --cg-text-on-primary
16
+ button: "#60e9f0", // --cg-tertiary
17
+ onButton: "#222222", // --cg-text-on-accent
18
+ soon: "#7a3d0a", // --cg-expired-strong
19
+ urgent: "#c42828", // --cg-danger-strong
20
+ soonFill: "#fdf3e0", // --cg-expired-fill
21
+ soonBorder: "#fedf89", // --cg-expired-border
22
+ soonDot: "#b0662a", // --cg-expired
23
+ urgentFill: "#fceded", // --cg-danger-fill
24
+ urgentBorder: "#ffd3cd", // --cg-danger-border
25
+ urgentDot: "#e53935", // --cg-danger
26
+ tilePage: "#3d7a7d", // --cg-tertiary 44% into --cg-ink
27
+ tileApp: "#5a47f0", // --cg-primary
28
+ tileAgent: "#637541", // --cg-secondary 44% into --cg-ink
29
+ fieldPage: "#e6fbfd", // --cg-tertiary 16% into --cg-neutral-0
30
+ fieldApp: "#ebe9fd", // --cg-primary 12% into --cg-neutral-0
31
+ fieldAgent: "#f3fae7", // --cg-secondary 16% into --cg-neutral-0
32
+ };
33
+ export const EMAIL_SHAPE = {
34
+ radiusContainer: 20, // --cg-radius-container
35
+ radiusButton: 16, // --cg-radius-xl
36
+ radiusCard: 14, // --cg-radius-lg
37
+ radiusTile: 12, // --cg-radius-md
38
+ fontBody: "'Space Grotesk Variable', 'Space Grotesk', 'Manrope Variable', 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", // --cg-font-body
39
+ fontUi: "'Manrope Variable', 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", // --cg-font-ui
40
+ fontDisplay: "'Tanker', 'Manrope Variable', 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", // --cg-font-display
41
+ fontMono: "'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace", // --cg-font-mono
42
+ displayTracking: "0.012em", // --cg-display-tracking
43
+ };
44
+ //# sourceMappingURL=palette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.js","sourceRoot":"","sources":["../../src/email/palette.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,gFAAgF;AAChF,iFAAiF;AACjF,mDAAmD;AAEnD,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,SAAS,EAAE,wBAAwB;IACzC,IAAI,EAAE,SAAS,EAAE,oBAAoB;IACrC,MAAM,EAAE,SAAS,EAAE,sBAAsB;IACzC,QAAQ,EAAE,SAAS,EAAE,uBAAuB;IAC5C,IAAI,EAAE,SAAS,EAAE,oBAAoB;IACrC,aAAa,EAAE,SAAS,EAAE,sBAAsB;IAChD,SAAS,EAAE,SAAS,EAAE,yBAAyB;IAC/C,OAAO,EAAE,SAAS,EAAE,eAAe;IACnC,SAAS,EAAE,SAAS,EAAE,uBAAuB;IAC7C,MAAM,EAAE,SAAS,EAAE,gBAAgB;IACnC,QAAQ,EAAE,SAAS,EAAE,sBAAsB;IAC3C,IAAI,EAAE,SAAS,EAAE,sBAAsB;IACvC,MAAM,EAAE,SAAS,EAAE,qBAAqB;IACxC,QAAQ,EAAE,SAAS,EAAE,oBAAoB;IACzC,UAAU,EAAE,SAAS,EAAE,sBAAsB;IAC7C,OAAO,EAAE,SAAS,EAAE,eAAe;IACnC,UAAU,EAAE,SAAS,EAAE,mBAAmB;IAC1C,YAAY,EAAE,SAAS,EAAE,qBAAqB;IAC9C,SAAS,EAAE,SAAS,EAAE,cAAc;IACpC,QAAQ,EAAE,SAAS,EAAE,kCAAkC;IACvD,OAAO,EAAE,SAAS,EAAE,eAAe;IACnC,SAAS,EAAE,SAAS,EAAE,mCAAmC;IACzD,SAAS,EAAE,SAAS,EAAE,wCAAwC;IAC9D,QAAQ,EAAE,SAAS,EAAE,uCAAuC;IAC5D,UAAU,EAAE,SAAS,EAAE,yCAAyC;CACxD,CAAA;AAIV,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,eAAe,EAAE,EAAE,EAAE,wBAAwB;IAC7C,YAAY,EAAE,EAAE,EAAE,iBAAiB;IACnC,UAAU,EAAE,EAAE,EAAE,iBAAiB;IACjC,UAAU,EAAE,EAAE,EAAE,iBAAiB;IACjC,QAAQ,EAAE,qIAAqI,EAAE,iBAAiB;IAClK,MAAM,EAAE,0FAA0F,EAAE,eAAe;IACnH,WAAW,EAAE,oGAAoG,EAAE,oBAAoB;IACvI,QAAQ,EAAE,6FAA6F,EAAE,iBAAiB;IAC1H,eAAe,EAAE,SAAS,EAAE,wBAAwB;CAC5C,CAAA"}
package/dist/index.d.ts CHANGED
@@ -31,6 +31,7 @@ export * from "./blocks/celebration.js";
31
31
  export * from "./blocks/cloudgrid-install.js";
32
32
  export * from "./blocks/command-field.js";
33
33
  export * from "./blocks/compare-table.js";
34
+ export * from "./blocks/confirm-delete-dialog.js";
34
35
  export * from "./blocks/creation-tile.js";
35
36
  export * from "./blocks/cta-banner.js";
36
37
  export * from "./blocks/drop-zone.js";
@@ -39,12 +40,14 @@ export * from "./blocks/entity-card.js";
39
40
  export * from "./blocks/entity-identity.js";
40
41
  export * from "./blocks/entity-status.js";
41
42
  export * from "./blocks/eyebrow.js";
43
+ export * from "./blocks/expiry-notice.js";
42
44
  export * from "./blocks/feature-cells.js";
43
45
  export * from "./blocks/feed-post.js";
44
46
  export * from "./blocks/hub-index.js";
45
47
  export * from "./blocks/install-content.js";
46
48
  export * from "./blocks/icons.js";
47
49
  export * from "./blocks/logo.js";
50
+ export * from "./blocks/notification-row.js";
48
51
  export * from "./blocks/onboarding-question.js";
49
52
  export * from "./blocks/option-card.js";
50
53
  export * from "./blocks/page-heading.js";
@@ -54,6 +57,7 @@ export * from "./blocks/pricing-tiers.js";
54
57
  export * from "./blocks/prompt-block.js";
55
58
  export * from "./blocks/quote.js";
56
59
  export * from "./blocks/rich-text.js";
60
+ export * from "./blocks/shelf.js";
57
61
  export * from "./blocks/showcase-scroll.js";
58
62
  export * from "./blocks/side-nav.js";
59
63
  export * from "./blocks/sign-in-options.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA;AAG/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AAGtC,cAAc,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA;AAG/B,cAAc,0BAA0B,CAAA;AACxC,cAAc,oBAAoB,CAAA;AAClC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,mCAAmC,CAAA;AACjD,cAAc,2BAA2B,CAAA;AACzC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,wBAAwB,CAAA;AAGtC,cAAc,uBAAuB,CAAA"}
package/dist/index.js CHANGED
@@ -48,6 +48,7 @@ export * from "./blocks/celebration.js";
48
48
  export * from "./blocks/cloudgrid-install.js";
49
49
  export * from "./blocks/command-field.js";
50
50
  export * from "./blocks/compare-table.js";
51
+ export * from "./blocks/confirm-delete-dialog.js";
51
52
  export * from "./blocks/creation-tile.js";
52
53
  export * from "./blocks/cta-banner.js";
53
54
  export * from "./blocks/drop-zone.js";
@@ -56,12 +57,14 @@ export * from "./blocks/entity-card.js";
56
57
  export * from "./blocks/entity-identity.js";
57
58
  export * from "./blocks/entity-status.js";
58
59
  export * from "./blocks/eyebrow.js";
60
+ export * from "./blocks/expiry-notice.js";
59
61
  export * from "./blocks/feature-cells.js";
60
62
  export * from "./blocks/feed-post.js";
61
63
  export * from "./blocks/hub-index.js";
62
64
  export * from "./blocks/install-content.js";
63
65
  export * from "./blocks/icons.js";
64
66
  export * from "./blocks/logo.js";
67
+ export * from "./blocks/notification-row.js";
65
68
  export * from "./blocks/onboarding-question.js";
66
69
  export * from "./blocks/option-card.js";
67
70
  export * from "./blocks/page-heading.js";
@@ -71,6 +74,7 @@ export * from "./blocks/pricing-tiers.js";
71
74
  export * from "./blocks/prompt-block.js";
72
75
  export * from "./blocks/quote.js";
73
76
  export * from "./blocks/rich-text.js";
77
+ export * from "./blocks/shelf.js";
74
78
  export * from "./blocks/showcase-scroll.js";
75
79
  export * from "./blocks/side-nav.js";
76
80
  export * from "./blocks/sign-in-options.js";