@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.
- package/README.md +32 -0
- package/dist/badge/brand.d.ts +8 -0
- package/dist/badge/brand.d.ts.map +1 -0
- package/dist/badge/brand.js +22 -0
- package/dist/badge/brand.js.map +1 -0
- package/dist/badge/css-base.d.ts +25 -0
- package/dist/badge/css-base.d.ts.map +1 -0
- package/dist/badge/css-base.js +103 -0
- package/dist/badge/css-base.js.map +1 -0
- package/dist/badge/css-owner.d.ts +7 -0
- package/dist/badge/css-owner.d.ts.map +1 -0
- package/dist/badge/css-owner.js +128 -0
- package/dist/badge/css-owner.js.map +1 -0
- package/dist/badge/css-visitor.d.ts +7 -0
- package/dist/badge/css-visitor.d.ts.map +1 -0
- package/dist/badge/css-visitor.js +75 -0
- package/dist/badge/css-visitor.js.map +1 -0
- package/dist/badge/html.d.ts +26 -0
- package/dist/badge/html.d.ts.map +1 -0
- package/dist/badge/html.js +55 -0
- package/dist/badge/html.js.map +1 -0
- package/dist/badge/index.d.ts +43 -0
- package/dist/badge/index.d.ts.map +1 -0
- package/dist/badge/index.js +46 -0
- package/dist/badge/index.js.map +1 -0
- package/dist/badge/marks.d.ts +45 -0
- package/dist/badge/marks.d.ts.map +1 -0
- package/dist/badge/marks.js +126 -0
- package/dist/badge/marks.js.map +1 -0
- package/dist/badge/owner.d.ts +213 -0
- package/dist/badge/owner.d.ts.map +1 -0
- package/dist/badge/owner.js +309 -0
- package/dist/badge/owner.js.map +1 -0
- package/dist/badge/palette.d.ts +23 -0
- package/dist/badge/palette.d.ts.map +1 -0
- package/dist/badge/palette.js +86 -0
- package/dist/badge/palette.js.map +1 -0
- package/dist/badge/root.d.ts +24 -0
- package/dist/badge/root.d.ts.map +1 -0
- package/dist/badge/root.js +11 -0
- package/dist/badge/root.js.map +1 -0
- package/dist/badge/shared.d.ts +56 -0
- package/dist/badge/shared.d.ts.map +1 -0
- package/dist/badge/shared.js +53 -0
- package/dist/badge/shared.js.map +1 -0
- package/dist/badge/visitor.d.ts +96 -0
- package/dist/badge/visitor.d.ts.map +1 -0
- package/dist/badge/visitor.js +119 -0
- package/dist/badge/visitor.js.map +1 -0
- package/dist/blocks/confirm-delete-dialog.d.ts +81 -0
- package/dist/blocks/confirm-delete-dialog.d.ts.map +1 -0
- package/dist/blocks/confirm-delete-dialog.js +89 -0
- package/dist/blocks/confirm-delete-dialog.js.map +1 -0
- package/dist/blocks/entity-status.d.ts +44 -1
- package/dist/blocks/entity-status.d.ts.map +1 -1
- package/dist/blocks/entity-status.js +26 -1
- package/dist/blocks/entity-status.js.map +1 -1
- package/dist/blocks/expiry-notice.d.ts +86 -0
- package/dist/blocks/expiry-notice.d.ts.map +1 -0
- package/dist/blocks/expiry-notice.js +81 -0
- package/dist/blocks/expiry-notice.js.map +1 -0
- package/dist/blocks/icons.d.ts +22 -0
- package/dist/blocks/icons.d.ts.map +1 -1
- package/dist/blocks/icons.js +22 -0
- package/dist/blocks/icons.js.map +1 -1
- package/dist/blocks/notification-row.d.ts +88 -0
- package/dist/blocks/notification-row.d.ts.map +1 -0
- package/dist/blocks/notification-row.js +32 -0
- package/dist/blocks/notification-row.js.map +1 -0
- package/dist/blocks/phosphor-marks.d.ts +10 -0
- package/dist/blocks/phosphor-marks.d.ts.map +1 -1
- package/dist/blocks/phosphor-marks.js +15 -0
- package/dist/blocks/phosphor-marks.js.map +1 -1
- package/dist/blocks/shelf.d.ts +384 -0
- package/dist/blocks/shelf.d.ts.map +1 -0
- package/dist/blocks/shelf.js +489 -0
- package/dist/blocks/shelf.js.map +1 -0
- package/dist/brand/badge/manrope-latin-wght-normal.woff2 +0 -0
- package/dist/brand/badge/space-grotesk-latin-wght-normal.woff2 +0 -0
- package/dist/brand/email/headline-activity.png +0 -0
- package/dist/brand/email/headline-expired.png +0 -0
- package/dist/brand/email/headline-expires-tomorrow.png +0 -0
- package/dist/brand/email/headline-expiring-soon.png +0 -0
- package/dist/brand/email/headline-invited.png +0 -0
- package/dist/brand/email/headline-sign-in-code.png +0 -0
- package/dist/brand/email/mesh.png +0 -0
- package/dist/brand/email/wordmark.png +0 -0
- package/dist/email/assets.d.ts +50 -0
- package/dist/email/assets.d.ts.map +1 -0
- package/dist/email/assets.js +16 -0
- package/dist/email/assets.js.map +1 -0
- package/dist/email/index.d.ts +204 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +429 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/palette.d.ts +40 -0
- package/dist/email/palette.d.ts.map +1 -0
- package/dist/email/palette.js +44 -0
- package/dist/email/palette.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/shadcn.css +41 -0
- package/dist/ui/dropdown-menu.d.ts +8 -1
- package/dist/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/ui/dropdown-menu.js +9 -2
- package/dist/ui/dropdown-menu.js.map +1 -1
- 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
|
+
"&": "&",
|
|
97
|
+
"<": "<",
|
|
98
|
+
">": ">",
|
|
99
|
+
'"': """,
|
|
100
|
+
"'": "'",
|
|
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;"> </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(/'/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)}${"‌ ".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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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";
|