@hraness/design-kit 0.36.5 → 0.39.0

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 (59) hide show
  1. package/MARKETING_COPY.md +2 -0
  2. package/README.md +77 -11
  3. package/dist/{chunk-xa28y4fg.js → chunk-1dgm85ta.js} +191 -55
  4. package/dist/chunk-6mx403v5.js +286 -0
  5. package/dist/{chunk-thv5t11w.js → chunk-dc8v05zh.js} +6 -137
  6. package/dist/{chunk-evb02bc1.js → chunk-fcs5qekr.js} +48 -1
  7. package/dist/chunk-fxwed3e5.js +775 -0
  8. package/dist/chunk-vy0pt84a.js +1807 -0
  9. package/dist/{chunk-sabcr66p.js → chunk-w1y1m3m7.js} +300 -1
  10. package/dist/index.js +24 -12
  11. package/dist/mockups/client.js +6 -654
  12. package/dist/mockups/index.js +29 -1797
  13. package/dist/provider-marks.js +1 -1
  14. package/dist/react/index.js +190 -5
  15. package/dist/react/server.js +5 -3
  16. package/dist/stylex-manifest.json +1 -1
  17. package/package.json +9 -5
  18. package/portfolio-inventory.json +1 -1
  19. package/src/compiler-foundation.css +2 -0
  20. package/src/design-gallery.css +12 -0
  21. package/src/index.ts +1 -0
  22. package/src/marketing-marquee.css +281 -0
  23. package/src/marketing-marquee.ts +206 -0
  24. package/src/mockups/client.tsx +157 -66
  25. package/src/mockups/core.tsx +30 -0
  26. package/src/mockups.css +158 -23
  27. package/src/provider-marks.generated.ts +92 -0
  28. package/src/provider-marks.ts +29 -4
  29. package/src/react/design-gallery.tsx +53 -0
  30. package/src/react/index.ts +1 -0
  31. package/src/react/marketing-marquee.tsx +71 -0
  32. package/src/react/server.ts +1 -0
  33. package/src/styles.css +2 -0
  34. package/vendor/provider-marks/BOOTSTRAP-ICONS-LICENSE +21 -0
  35. package/vendor/provider-marks/UPSTREAM.md +28 -0
  36. package/vendor/provider-marks/bootstrap-icons/calendar-event-fill.svg +3 -0
  37. package/vendor/provider-marks/bootstrap-icons/filetype-csv.svg +3 -0
  38. package/vendor/provider-marks/bootstrap-icons/globe2.svg +3 -0
  39. package/vendor/provider-marks/bootstrap-icons/linkedin.svg +3 -0
  40. package/vendor/provider-marks/bootstrap-icons/microsoft.svg +3 -0
  41. package/vendor/provider-marks/bootstrap-icons/person-vcard-fill.svg +3 -0
  42. package/vendor/provider-marks/bootstrap-icons/shop.svg +3 -0
  43. package/vendor/provider-marks/simple-icons/apple.svg +1 -0
  44. package/vendor/provider-marks/simple-icons/bluesky.svg +1 -0
  45. package/vendor/provider-marks/simple-icons/facebook.svg +1 -0
  46. package/vendor/provider-marks/simple-icons/github.svg +1 -0
  47. package/vendor/provider-marks/simple-icons/gmail.svg +1 -0
  48. package/vendor/provider-marks/simple-icons/google.svg +1 -0
  49. package/vendor/provider-marks/simple-icons/instagram.svg +1 -0
  50. package/vendor/provider-marks/simple-icons/reddit.svg +1 -0
  51. package/vendor/provider-marks/simple-icons/substack.svg +1 -0
  52. package/vendor/provider-marks/simple-icons/telegram.svg +1 -0
  53. package/vendor/provider-marks/simple-icons/threads.svg +1 -0
  54. package/vendor/provider-marks/simple-icons/tiktok.svg +1 -0
  55. package/vendor/provider-marks/simple-icons/twitch.svg +1 -0
  56. package/vendor/provider-marks/simple-icons/x.svg +1 -0
  57. package/vendor/provider-marks/simple-icons/ycombinator.svg +1 -0
  58. package/vendor/provider-marks/simple-icons/youtube.svg +1 -0
  59. package/dist/chunk-gmea6p0d.js +0 -13
@@ -0,0 +1,286 @@
1
+ import {
2
+ ARTICLE_BYLINE_PREFIX,
3
+ ARTICLE_SOURCES_HEADING,
4
+ ARTICLE_TOC_LABEL,
5
+ articleProvenanceSentence,
6
+ assertArticleAuthor,
7
+ assertArticleCalloutTone,
8
+ assertArticleDates,
9
+ assertArticleHref,
10
+ formatArticleDate
11
+ } from "./chunk-77391vmq.js";
12
+ import {
13
+ providerMark,
14
+ providerMarkMonogram
15
+ } from "./chunk-w1y1m3m7.js";
16
+
17
+ // src/article-html.ts
18
+ var ROOT_CLASS = "plain-site plain-publication plain-publication--embedded";
19
+ var SEPARATOR = '<span aria-hidden="true"> · </span>';
20
+ var ESCAPES = {
21
+ '"': "&quot;",
22
+ "&": "&amp;",
23
+ "'": "&#x27;",
24
+ "<": "&lt;",
25
+ ">": "&gt;"
26
+ };
27
+ function escapeArticleHtml(value) {
28
+ return value.replace(/["&'<>]/gu, (character) => ESCAPES[character] ?? character);
29
+ }
30
+ function classes(...values) {
31
+ return values.filter((value) => value !== undefined && value !== "").join(" ");
32
+ }
33
+ function dateHtml(label, value) {
34
+ return `${label} <time dateTime="${escapeArticleHtml(value)}">${escapeArticleHtml(formatArticleDate(value))}</time>`;
35
+ }
36
+ function present(value) {
37
+ return value !== undefined && value !== "";
38
+ }
39
+ function renderArticleBylineHtml(author) {
40
+ assertArticleAuthor(author);
41
+ const name = escapeArticleHtml(author.name);
42
+ const linked = author.href === undefined ? name : `<a href="${escapeArticleHtml(author.href)}" rel="author">${name}</a>`;
43
+ return `<span class="plain-publication__byline" data-author-kind="${author.kind}">${ARTICLE_BYLINE_PREFIX} ${linked}</span>`;
44
+ }
45
+ function renderArticleProvenanceHtml(provenance) {
46
+ const sentence = articleProvenanceSentence(provenance);
47
+ return `<p class="plain-publication__provenance" data-drafting="${escapeArticleHtml(provenance.drafting)}" data-reviewer-type="${escapeArticleHtml(provenance.review?.reviewerType ?? "none")}">${escapeArticleHtml(sentence)}</p>`;
48
+ }
49
+ function renderArticleHtml(input) {
50
+ const headingId = input.headingId ?? "article-title";
51
+ const {
52
+ published,
53
+ updated,
54
+ showDates = true
55
+ } = input;
56
+ assertArticleDates(updated === undefined ? {
57
+ published
58
+ } : {
59
+ published,
60
+ updated
61
+ });
62
+ const toc = input.toc ?? [];
63
+ for (const item of toc) {
64
+ if (!item.href.startsWith("#") || item.href.length < 2)
65
+ throw new RangeError("Contents links must point to a heading in this article.");
66
+ }
67
+ const tocId = `${headingId}-contents`;
68
+ const meta = [input.author === undefined ? "" : renderArticleBylineHtml(input.author), showDates ? dateHtml("Published", published) : "", showDates && updated !== undefined ? dateHtml("Updated", updated) : ""].filter(Boolean).join(SEPARATOR);
69
+ const header = ['<header class="plain-publication__article-header">', present(input.eyebrow) ? `<p class="plain-publication__eyebrow">${escapeArticleHtml(input.eyebrow)}</p>` : "", `<h1 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(input.heading)}</h1>`, present(input.dek) ? `<p class="plain-publication__article-dek">${escapeArticleHtml(input.dek)}</p>` : "", meta === "" ? "" : `<p class="plain-publication__article-meta">${meta}</p>`, input.provenance === null ? "" : renderArticleProvenanceHtml(input.provenance), "</header>"].join("");
70
+ const nav = toc.length === 0 ? "" : [`<nav aria-labelledby="${escapeArticleHtml(tocId)}" class="plain-publication__toc">`, `<p id="${escapeArticleHtml(tocId)}">${escapeArticleHtml(input.tocLabel ?? ARTICLE_TOC_LABEL)}</p>`, "<ol>", ...toc.map((item) => `<li><a href="${escapeArticleHtml(item.href)}">${escapeArticleHtml(item.label)}</a></li>`), "</ol></nav>"].join("");
71
+ return [`<article aria-labelledby="${escapeArticleHtml(headingId)}" class="${escapeArticleHtml(classes(ROOT_CLASS, "plain-publication__article", input.className))}" data-hraness-article="" data-toc="${toc.length > 0 ? "aside" : "none"}"${input.id === undefined ? "" : ` id="${escapeArticleHtml(input.id)}"`}>`, header, '<div class="plain-publication__article-layout">', nav, `<div class="plain-publication__article-body">${input.bodyHtml}</div>`, "</div>", present(input.afterHtml) ? `<footer class="plain-publication__article-footer">${input.afterHtml}</footer>` : "", "</article>"].join("");
72
+ }
73
+ function renderArticleSourcesHtml({
74
+ heading = ARTICLE_SOURCES_HEADING,
75
+ headingId = "article-sources",
76
+ showDates = true,
77
+ sources
78
+ }) {
79
+ if (sources.length === 0)
80
+ return "";
81
+ for (const source of sources) {
82
+ assertArticleHref(source.href);
83
+ formatArticleDate(source.checkedOn);
84
+ }
85
+ return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="plain-publication__sources">`, `<h2 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</h2>`, "<ol>", ...sources.map((source) => {
86
+ const meta = [present(source.publisher) ? escapeArticleHtml(source.publisher) : "", showDates ? dateHtml("Checked", source.checkedOn) : ""].filter(Boolean).join(SEPARATOR);
87
+ return [`<li><a href="${escapeArticleHtml(source.href)}">${escapeArticleHtml(source.title)}</a>`, meta === "" ? "" : `<span>${meta}</span>`, "</li>"].join("");
88
+ }), "</ol></section>"].join("");
89
+ }
90
+ function renderArticleCalloutHtml(input) {
91
+ const tone = input.tone ?? "note";
92
+ assertArticleCalloutTone(tone);
93
+ const body = input.text === undefined ? input.bodyHtml : `<p>${escapeArticleHtml(input.text)}</p>`;
94
+ return `<div class="plain-publication__callout" data-tone="${tone}" role="note">${present(input.label) ? `<strong>${escapeArticleHtml(input.label)}</strong>` : ""}${body}</div>`;
95
+ }
96
+ function assertArticleMark(mark) {
97
+ if (!mark.startsWith("data:image/svg+xml,"))
98
+ assertArticleHref(mark);
99
+ }
100
+ function renderArticleRelatedHtml({
101
+ heading = "Related products",
102
+ headingId = "article-related-products",
103
+ items
104
+ }) {
105
+ if (items.length === 0)
106
+ return "";
107
+ for (const item of items) {
108
+ assertArticleHref(item.href);
109
+ if (present(item.mark))
110
+ assertArticleMark(item.mark);
111
+ }
112
+ return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="plain-publication__related">`, `<div class="plain-publication__section-heading"><h2 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</h2></div>`, '<div class="plain-publication__related-grid">', ...items.map((item) => [`<a href="${escapeArticleHtml(item.href)}">`, present(item.mark) ? `<img alt="" class="plain-publication__related-mark" decoding="async" height="44" src="${escapeArticleHtml(item.mark)}" width="44">` : "", `<span class="plain-publication__related-text"><strong>${escapeArticleHtml(item.name)}</strong>`, `<span>${escapeArticleHtml(item.role ?? item.relationship)}</span></span></a>`].join("")), "</div></section>"].join("");
113
+ }
114
+ function renderArticleIndexHtml({
115
+ className,
116
+ heading,
117
+ headingId,
118
+ headingLevel = 2,
119
+ id,
120
+ items,
121
+ showDates = true,
122
+ summary
123
+ }) {
124
+ if (![1, 2, 3, 4, 5].includes(headingLevel))
125
+ throw new RangeError("Article index heading level must be 1 to 5.");
126
+ const hrefs = new Set;
127
+ for (const item of items) {
128
+ assertArticleHref(item.href);
129
+ assertArticleDates(item.updated === undefined ? {
130
+ published: item.published
131
+ } : {
132
+ published: item.published,
133
+ updated: item.updated
134
+ });
135
+ if (hrefs.has(item.href))
136
+ throw new RangeError(`Article index lists ${item.href} more than once.`);
137
+ hrefs.add(item.href);
138
+ }
139
+ const heading1 = `h${headingLevel}`;
140
+ const entry = `h${headingLevel + 1}`;
141
+ return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="${escapeArticleHtml(classes(ROOT_CLASS, "plain-publication__list", className))}" data-hraness-article-index=""${id === undefined ? "" : ` id="${escapeArticleHtml(id)}"`}>`, `<div class="plain-publication__section-heading"><${heading1} id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</${heading1}>`, present(summary) ? `<p>${escapeArticleHtml(summary)}</p>` : "", "</div>", '<div class="plain-publication__article-list">', ...items.map((item) => ['<article class="plain-publication__entry">', present(item.eyebrow) ? `<p class="plain-publication__entry-label">${escapeArticleHtml(item.eyebrow)}</p>` : "", `<${entry} class="plain-publication__entry-title"><a href="${escapeArticleHtml(item.href)}">${escapeArticleHtml(item.title)}</a></${entry}>`, `<p class="plain-publication__entry-dek">${escapeArticleHtml(item.dek)}</p>`, showDates ? ['<p class="plain-publication__entry-meta">', dateHtml("Published", item.published), item.updated === undefined ? "" : SEPARATOR + dateHtml("Updated", item.updated), "</p>"].join("") : "", "</article>"].join("")), "</div></section>"].join("");
142
+ }
143
+
144
+ // src/marketing-marquee.ts
145
+ var MARKETING_MARQUEE_COUNT_TOKEN = "{count}";
146
+ var MARKETING_MARQUEE_MAX_ITEMS = 64;
147
+ var MARKETING_MARQUEE_DEFAULT_PAUSE_LABEL = "Pause scrolling";
148
+ var MIN_LOOP_ITEMS = 20;
149
+ var MAX_NAME_LENGTH = 64;
150
+ var MAX_LABEL_LENGTH = 120;
151
+ var ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/u;
152
+ var FORBIDDEN_ARTWORK = /<script|<foreignObject|on[a-z]+\s*=|javascript:/iu;
153
+ var ROOT_CLASS2 = "hraness-marketing-marquee";
154
+ var MARKETING_MARQUEE_CONTROL_ICONS = {
155
+ pause: "M5 3.25a1 1 0 0 1 1 1v7.5a1 1 0 0 1-2 0v-7.5a1 1 0 0 1 1-1Zm6 0a1 1 0 0 1 1 1v7.5a1 1 0 0 1-2 0v-7.5a1 1 0 0 1 1-1Z",
156
+ play: "M5.25 3.6v8.8a.75.75 0 0 0 1.14.64l7.04-4.4a.75.75 0 0 0 0-1.28L6.39 2.96a.75.75 0 0 0-1.14.64Z"
157
+ };
158
+ function requireText(value, field, limit) {
159
+ const text = value.trim();
160
+ if (text === "")
161
+ throw new RangeError(`Marketing marquee ${field} must not be empty.`);
162
+ if (text.length > limit)
163
+ throw new RangeError(`Marketing marquee ${field} must be at most ${limit} characters.`);
164
+ return text;
165
+ }
166
+ function resolveMark(mark, name) {
167
+ if (mark === undefined)
168
+ return providerMark(name);
169
+ if (typeof mark === "string")
170
+ return providerMark(mark);
171
+ return mark;
172
+ }
173
+ function resolveMarketingMarquee(input) {
174
+ if (!ID_PATTERN.test(input.id))
175
+ throw new RangeError("Marketing marquee id must start with a letter and use at most 64 letters, digits, hyphens, or underscores.");
176
+ const label = requireText(input.label, "label", MAX_LABEL_LENGTH);
177
+ const parts = label.split(MARKETING_MARQUEE_COUNT_TOKEN);
178
+ if (parts.length !== 2)
179
+ throw new RangeError(`Marketing marquee label must contain ${MARKETING_MARQUEE_COUNT_TOKEN} exactly once.`);
180
+ if (input.items.length === 0)
181
+ throw new RangeError("Marketing marquee needs at least one item.");
182
+ if (input.items.length > MARKETING_MARQUEE_MAX_ITEMS)
183
+ throw new RangeError(`Marketing marquee shows at most ${MARKETING_MARQUEE_MAX_ITEMS} items.`);
184
+ if (input.align !== undefined && input.align !== "start" && input.align !== "center")
185
+ throw new RangeError("Marketing marquee align must be start or center.");
186
+ const names = new Set;
187
+ const symbols = [];
188
+ const symbolIds = new Map;
189
+ const items = input.items.map((item) => {
190
+ const name = requireText(item.name, "item name", MAX_NAME_LENGTH);
191
+ if (names.has(name))
192
+ throw new RangeError(`Marketing marquee lists ${JSON.stringify(name)} more than once.`);
193
+ names.add(name);
194
+ const descriptor = resolveMark(item.mark, name);
195
+ if (descriptor === undefined || descriptor.glyph.body === "") {
196
+ return {
197
+ name,
198
+ mark: {
199
+ kind: "monogram",
200
+ monogram: descriptor?.monogram ?? providerMarkMonogram(name)
201
+ }
202
+ };
203
+ }
204
+ const {
205
+ viewBox,
206
+ body
207
+ } = descriptor.glyph;
208
+ if (FORBIDDEN_ARTWORK.test(body) || /["<>]/u.test(viewBox))
209
+ throw new RangeError(`Marketing marquee artwork for ${JSON.stringify(name)} contains unsupported markup.`);
210
+ const key = `${viewBox}
211
+ ${body}`;
212
+ let symbolId = symbolIds.get(key);
213
+ if (symbolId === undefined) {
214
+ symbolId = `${input.id}-mark-${symbols.length}`;
215
+ symbolIds.set(key, symbolId);
216
+ symbols.push({
217
+ body,
218
+ id: symbolId,
219
+ viewBox
220
+ });
221
+ }
222
+ return {
223
+ name,
224
+ mark: {
225
+ kind: "glyph",
226
+ symbolId
227
+ }
228
+ };
229
+ });
230
+ let action = null;
231
+ if (input.action !== undefined) {
232
+ assertArticleHref(input.action.href);
233
+ action = {
234
+ href: input.action.href,
235
+ label: requireText(input.action.label, "action label", MAX_LABEL_LENGTH)
236
+ };
237
+ }
238
+ return {
239
+ action,
240
+ align: input.align ?? "start",
241
+ className: [ROOT_CLASS2, input.className?.trim()].filter(Boolean).join(" "),
242
+ copies: Math.max(2, 1 + Math.ceil(MIN_LOOP_ITEMS / items.length)),
243
+ id: input.id,
244
+ items,
245
+ label: {
246
+ after: parts[1] ?? "",
247
+ before: parts[0] ?? "",
248
+ count: String(items.length)
249
+ },
250
+ labelId: `${input.id}-label`,
251
+ pauseLabel: requireText(input.pauseLabel ?? MARKETING_MARQUEE_DEFAULT_PAUSE_LABEL, "pause label", MAX_LABEL_LENGTH),
252
+ symbols,
253
+ toggleId: `${input.id}-pause`
254
+ };
255
+ }
256
+ function itemHtml(item) {
257
+ const mark = item.mark.kind === "glyph" ? `<svg aria-hidden="true" class="${ROOT_CLASS2}__mark" fill="currentColor" focusable="false" height="20" width="20"><use href="#${item.mark.symbolId}"></use></svg>` : `<span aria-hidden="true" class="${ROOT_CLASS2}__monogram">${escapeArticleHtml(item.mark.monogram)}</span>`;
258
+ return `<li class="${ROOT_CLASS2}__item">${mark}<span class="${ROOT_CLASS2}__name">${escapeArticleHtml(item.name)}</span></li>`;
259
+ }
260
+ function controlIconHtml(icon) {
261
+ return `<svg aria-hidden="true" class="${ROOT_CLASS2}__control-icon" data-icon="${icon}" fill="currentColor" focusable="false" height="16" viewBox="0 0 16 16" width="16"><path d="${MARKETING_MARQUEE_CONTROL_ICONS[icon]}"></path></svg>`;
262
+ }
263
+ function renderMarketingMarqueeHtml(input) {
264
+ const marquee = resolveMarketingMarquee(input);
265
+ const items = marquee.items.map(itemHtml).join("");
266
+ const lists = Array.from({
267
+ length: marquee.copies
268
+ }, (_, index) => `<ul${index === 0 ? "" : ' aria-hidden="true"'} class="${ROOT_CLASS2}__list">${items}</ul>`).join("");
269
+ const sprite = marquee.symbols.length === 0 ? "" : `<svg aria-hidden="true" class="${ROOT_CLASS2}__sprite" focusable="false" height="0" width="0">${marquee.symbols.map((symbol) => `<symbol id="${symbol.id}" viewBox="${symbol.viewBox}">${symbol.body}</symbol>`).join("")}</svg>`;
270
+ const action = marquee.action === null ? "" : `<a class="${ROOT_CLASS2}__action hraness-text-link" href="${escapeArticleHtml(marquee.action.href)}">${escapeArticleHtml(marquee.action.label)}</a>`;
271
+ return [`<section aria-labelledby="${marquee.labelId}" class="${escapeArticleHtml(marquee.className)}" data-align="${marquee.align}" data-hraness-marketing="marquee" id="${marquee.id}">`, sprite, `<div class="${ROOT_CLASS2}__header">`, `<p class="${ROOT_CLASS2}__label" id="${marquee.labelId}">${escapeArticleHtml(marquee.label.before)}<strong class="${ROOT_CLASS2}__count">${marquee.label.count}</strong>${escapeArticleHtml(marquee.label.after)}</p>`, action, "</div>", `<input class="${ROOT_CLASS2}__toggle" id="${marquee.toggleId}" type="checkbox"/>`, `<div class="${ROOT_CLASS2}__viewport"><div class="${ROOT_CLASS2}__track">${lists}</div></div>`, `<label class="${ROOT_CLASS2}__control" for="${marquee.toggleId}"><span class="${ROOT_CLASS2}__control-text">${escapeArticleHtml(marquee.pauseLabel)}</span>${controlIconHtml("pause")}${controlIconHtml("play")}</label>`, "</section>"].join("");
272
+ }
273
+
274
+ // src/diagrams.ts
275
+ var diagramMetrics = Object.freeze({
276
+ labelSize: 20,
277
+ detailSize: 16,
278
+ strokeWidth: 1.5,
279
+ arrowheadSize: 6,
280
+ nodePadding: 24,
281
+ nodeGap: 48,
282
+ minimumCanvasWidth: 640,
283
+ fontFamily: '"Nebula Sans", ui-sans-serif, system-ui, sans-serif'
284
+ });
285
+
286
+ export { escapeArticleHtml, renderArticleBylineHtml, renderArticleProvenanceHtml, renderArticleHtml, renderArticleSourcesHtml, renderArticleCalloutHtml, renderArticleRelatedHtml, renderArticleIndexHtml, MARKETING_MARQUEE_COUNT_TOKEN, MARKETING_MARQUEE_MAX_ITEMS, MARKETING_MARQUEE_DEFAULT_PAUSE_LABEL, MARKETING_MARQUEE_CONTROL_ICONS, resolveMarketingMarquee, renderMarketingMarqueeHtml, diagramMetrics };
@@ -1,19 +1,14 @@
1
1
  import {
2
- ARTICLE_BYLINE_PREFIX,
3
- ARTICLE_SOURCES_HEADING,
4
- ARTICLE_TOC_LABEL,
5
- articleProvenanceSentence,
6
- assertArticleAuthor,
7
- assertArticleCalloutTone,
8
- assertArticleDates,
9
- assertArticleHref,
10
- formatArticleDate
2
+ escapeArticleHtml
3
+ } from "./chunk-6mx403v5.js";
4
+ import {
5
+ assertArticleHref
11
6
  } from "./chunk-77391vmq.js";
12
7
  import {
13
8
  mixPaletteColor,
14
9
  paletteContrast,
15
10
  readablePaletteColor
16
- } from "./chunk-sabcr66p.js";
11
+ } from "./chunk-w1y1m3m7.js";
17
12
 
18
13
  // src/palettes.ts
19
14
  var designPalettes = ["catppuccin", "gruvbox", "rose-pine", "tokyo-night", "paper"];
@@ -424,132 +419,6 @@ function getDesignPaletteTheme(palette, mode) {
424
419
  background: paletteColors[palette][mode].background
425
420
  };
426
421
  }
427
- // src/article-html.ts
428
- var ROOT_CLASS = "plain-site plain-publication plain-publication--embedded";
429
- var SEPARATOR = '<span aria-hidden="true"> · </span>';
430
- var ESCAPES = {
431
- '"': "&quot;",
432
- "&": "&amp;",
433
- "'": "&#x27;",
434
- "<": "&lt;",
435
- ">": "&gt;"
436
- };
437
- function escapeArticleHtml(value) {
438
- return value.replace(/["&'<>]/gu, (character) => ESCAPES[character] ?? character);
439
- }
440
- function classes2(...values) {
441
- return values.filter((value) => value !== undefined && value !== "").join(" ");
442
- }
443
- function dateHtml(label, value) {
444
- return `${label} <time dateTime="${escapeArticleHtml(value)}">${escapeArticleHtml(formatArticleDate(value))}</time>`;
445
- }
446
- function present(value) {
447
- return value !== undefined && value !== "";
448
- }
449
- function renderArticleBylineHtml(author) {
450
- assertArticleAuthor(author);
451
- const name = escapeArticleHtml(author.name);
452
- const linked = author.href === undefined ? name : `<a href="${escapeArticleHtml(author.href)}" rel="author">${name}</a>`;
453
- return `<span class="plain-publication__byline" data-author-kind="${author.kind}">${ARTICLE_BYLINE_PREFIX} ${linked}</span>`;
454
- }
455
- function renderArticleProvenanceHtml(provenance) {
456
- const sentence = articleProvenanceSentence(provenance);
457
- return `<p class="plain-publication__provenance" data-drafting="${escapeArticleHtml(provenance.drafting)}" data-reviewer-type="${escapeArticleHtml(provenance.review?.reviewerType ?? "none")}">${escapeArticleHtml(sentence)}</p>`;
458
- }
459
- function renderArticleHtml(input) {
460
- const headingId = input.headingId ?? "article-title";
461
- const {
462
- published,
463
- updated,
464
- showDates = true
465
- } = input;
466
- assertArticleDates(updated === undefined ? {
467
- published
468
- } : {
469
- published,
470
- updated
471
- });
472
- const toc = input.toc ?? [];
473
- for (const item of toc) {
474
- if (!item.href.startsWith("#") || item.href.length < 2)
475
- throw new RangeError("Contents links must point to a heading in this article.");
476
- }
477
- const tocId = `${headingId}-contents`;
478
- const meta = [input.author === undefined ? "" : renderArticleBylineHtml(input.author), showDates ? dateHtml("Published", published) : "", showDates && updated !== undefined ? dateHtml("Updated", updated) : ""].filter(Boolean).join(SEPARATOR);
479
- const header = ['<header class="plain-publication__article-header">', present(input.eyebrow) ? `<p class="plain-publication__eyebrow">${escapeArticleHtml(input.eyebrow)}</p>` : "", `<h1 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(input.heading)}</h1>`, present(input.dek) ? `<p class="plain-publication__article-dek">${escapeArticleHtml(input.dek)}</p>` : "", meta === "" ? "" : `<p class="plain-publication__article-meta">${meta}</p>`, input.provenance === null ? "" : renderArticleProvenanceHtml(input.provenance), "</header>"].join("");
480
- const nav = toc.length === 0 ? "" : [`<nav aria-labelledby="${escapeArticleHtml(tocId)}" class="plain-publication__toc">`, `<p id="${escapeArticleHtml(tocId)}">${escapeArticleHtml(input.tocLabel ?? ARTICLE_TOC_LABEL)}</p>`, "<ol>", ...toc.map((item) => `<li><a href="${escapeArticleHtml(item.href)}">${escapeArticleHtml(item.label)}</a></li>`), "</ol></nav>"].join("");
481
- return [`<article aria-labelledby="${escapeArticleHtml(headingId)}" class="${escapeArticleHtml(classes2(ROOT_CLASS, "plain-publication__article", input.className))}" data-hraness-article="" data-toc="${toc.length > 0 ? "aside" : "none"}"${input.id === undefined ? "" : ` id="${escapeArticleHtml(input.id)}"`}>`, header, '<div class="plain-publication__article-layout">', nav, `<div class="plain-publication__article-body">${input.bodyHtml}</div>`, "</div>", present(input.afterHtml) ? `<footer class="plain-publication__article-footer">${input.afterHtml}</footer>` : "", "</article>"].join("");
482
- }
483
- function renderArticleSourcesHtml({
484
- heading = ARTICLE_SOURCES_HEADING,
485
- headingId = "article-sources",
486
- showDates = true,
487
- sources
488
- }) {
489
- if (sources.length === 0)
490
- return "";
491
- for (const source of sources) {
492
- assertArticleHref(source.href);
493
- formatArticleDate(source.checkedOn);
494
- }
495
- return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="plain-publication__sources">`, `<h2 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</h2>`, "<ol>", ...sources.map((source) => {
496
- const meta = [present(source.publisher) ? escapeArticleHtml(source.publisher) : "", showDates ? dateHtml("Checked", source.checkedOn) : ""].filter(Boolean).join(SEPARATOR);
497
- return [`<li><a href="${escapeArticleHtml(source.href)}">${escapeArticleHtml(source.title)}</a>`, meta === "" ? "" : `<span>${meta}</span>`, "</li>"].join("");
498
- }), "</ol></section>"].join("");
499
- }
500
- function renderArticleCalloutHtml(input) {
501
- const tone = input.tone ?? "note";
502
- assertArticleCalloutTone(tone);
503
- const body = input.text === undefined ? input.bodyHtml : `<p>${escapeArticleHtml(input.text)}</p>`;
504
- return `<div class="plain-publication__callout" data-tone="${tone}" role="note">${present(input.label) ? `<strong>${escapeArticleHtml(input.label)}</strong>` : ""}${body}</div>`;
505
- }
506
- function assertArticleMark(mark) {
507
- if (!mark.startsWith("data:image/svg+xml,"))
508
- assertArticleHref(mark);
509
- }
510
- function renderArticleRelatedHtml({
511
- heading = "Related products",
512
- headingId = "article-related-products",
513
- items
514
- }) {
515
- if (items.length === 0)
516
- return "";
517
- for (const item of items) {
518
- assertArticleHref(item.href);
519
- if (present(item.mark))
520
- assertArticleMark(item.mark);
521
- }
522
- return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="plain-publication__related">`, `<div class="plain-publication__section-heading"><h2 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</h2></div>`, '<div class="plain-publication__related-grid">', ...items.map((item) => [`<a href="${escapeArticleHtml(item.href)}">`, present(item.mark) ? `<img alt="" class="plain-publication__related-mark" decoding="async" height="44" src="${escapeArticleHtml(item.mark)}" width="44">` : "", `<span class="plain-publication__related-text"><strong>${escapeArticleHtml(item.name)}</strong>`, `<span>${escapeArticleHtml(item.role ?? item.relationship)}</span></span></a>`].join("")), "</div></section>"].join("");
523
- }
524
- function renderArticleIndexHtml({
525
- className,
526
- heading,
527
- headingId,
528
- headingLevel = 2,
529
- id,
530
- items,
531
- showDates = true,
532
- summary
533
- }) {
534
- if (![1, 2, 3, 4, 5].includes(headingLevel))
535
- throw new RangeError("Article index heading level must be 1 to 5.");
536
- const hrefs = new Set;
537
- for (const item of items) {
538
- assertArticleHref(item.href);
539
- assertArticleDates(item.updated === undefined ? {
540
- published: item.published
541
- } : {
542
- published: item.published,
543
- updated: item.updated
544
- });
545
- if (hrefs.has(item.href))
546
- throw new RangeError(`Article index lists ${item.href} more than once.`);
547
- hrefs.add(item.href);
548
- }
549
- const heading1 = `h${headingLevel}`;
550
- const entry = `h${headingLevel + 1}`;
551
- return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="${escapeArticleHtml(classes2(ROOT_CLASS, "plain-publication__list", className))}" data-hraness-article-index=""${id === undefined ? "" : ` id="${escapeArticleHtml(id)}"`}>`, `<div class="plain-publication__section-heading"><${heading1} id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</${heading1}>`, present(summary) ? `<p>${escapeArticleHtml(summary)}</p>` : "", "</div>", '<div class="plain-publication__article-list">', ...items.map((item) => ['<article class="plain-publication__entry">', present(item.eyebrow) ? `<p class="plain-publication__entry-label">${escapeArticleHtml(item.eyebrow)}</p>` : "", `<${entry} class="plain-publication__entry-title"><a href="${escapeArticleHtml(item.href)}">${escapeArticleHtml(item.title)}</a></${entry}>`, `<p class="plain-publication__entry-dek">${escapeArticleHtml(item.dek)}</p>`, showDates ? ['<p class="plain-publication__entry-meta">', dateHtml("Published", item.published), item.updated === undefined ? "" : SEPARATOR + dateHtml("Updated", item.updated), "</p>"].join("") : "", "</article>"].join("")), "</div></section>"].join("");
552
- }
553
422
  // src/status-page.ts
554
423
  var STATUS_PAGE_MAX_NEXT = 3;
555
424
  var STATUS_PAGE_MAX_ROUTES = 2000;
@@ -1243,4 +1112,4 @@ function themeFor(mode) {
1243
1112
  return colors[mode];
1244
1113
  }
1245
1114
 
1246
- export { designPalettes, designPaletteLabels, isDesignPalette, designPaletteSources, paletteColors, designThemes, defaultDesignTheme, designThemeStorageKey, isDesignTheme, normalizeDesignTheme, designThemeLabel, resolveDesignTheme, defaultDesignPalettePreference, designPaletteStorageKey, parseDesignPalettePreference, normalizeDesignPalettePreference, resolveDesignPalettePreference, getDesignPaletteTheme, escapeArticleHtml, renderArticleBylineHtml, renderArticleProvenanceHtml, renderArticleHtml, renderArticleSourcesHtml, renderArticleCalloutHtml, renderArticleRelatedHtml, renderArticleIndexHtml, STATUS_PAGE_MAX_NEXT, STATUS_PAGE_MAX_ROUTES, STATUS_PAGE_BACK_LABEL, STATUS_PAGE_HINT_PREFIX, STATUS_PAGE_NEXT_HEADING_ID, STATUS_PAGE_AGENT_PREFIX, resolveStatusPage, statusPageRoutesAttribute, parseStatusPageRoutes, normalizeStatusPath, suggestStatusRoute, renderStatusPageHtml, relativeTimeUnits, parseRelativeTimeInput, resolveRelativeTime, formatRelativeTime, MAX_AGENT_SETUP_URL, agentSetupTargets, colors, auroraColors, chromeColors, chromeGradientStops, spacing, radius, controlRadius, layout, siteThemes, interaction, motion, elevation, stacking, breakpoints, iconography, typeScale, fontWeights, fontFamilies, fontFallbacks, typography, themeFor };
1115
+ export { designPalettes, designPaletteLabels, isDesignPalette, designPaletteSources, paletteColors, designThemes, defaultDesignTheme, designThemeStorageKey, isDesignTheme, normalizeDesignTheme, designThemeLabel, resolveDesignTheme, defaultDesignPalettePreference, designPaletteStorageKey, parseDesignPalettePreference, normalizeDesignPalettePreference, resolveDesignPalettePreference, getDesignPaletteTheme, STATUS_PAGE_MAX_NEXT, STATUS_PAGE_MAX_ROUTES, STATUS_PAGE_BACK_LABEL, STATUS_PAGE_HINT_PREFIX, STATUS_PAGE_NEXT_HEADING_ID, STATUS_PAGE_AGENT_PREFIX, resolveStatusPage, statusPageRoutesAttribute, parseStatusPageRoutes, normalizeStatusPath, suggestStatusRoute, renderStatusPageHtml, relativeTimeUnits, parseRelativeTimeInput, resolveRelativeTime, formatRelativeTime, MAX_AGENT_SETUP_URL, agentSetupTargets, colors, auroraColors, chromeColors, chromeGradientStops, spacing, radius, controlRadius, layout, siteThemes, interaction, motion, elevation, stacking, breakpoints, iconography, typeScale, fontWeights, fontFamilies, fontFallbacks, typography, themeFor };
@@ -1,3 +1,9 @@
1
+ import {
2
+ providerMark,
3
+ providerMarkMonogram,
4
+ providerMarkOnAccent
5
+ } from "./chunk-w1y1m3m7.js";
6
+
1
7
  // src/mockups/core.tsx
2
8
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
9
  function joinMockupClasses(...values) {
@@ -501,6 +507,47 @@ function MockupGlyph({
501
507
  children: GLYPHS[name]
502
508
  });
503
509
  }
510
+ function MockupBrandMark({
511
+ className,
512
+ name,
513
+ size = 32,
514
+ variant = "tile"
515
+ }) {
516
+ if (!(size > 0))
517
+ throw new RangeError("MockupBrandMark size must be positive.");
518
+ const mark = providerMark(name);
519
+ const style = {
520
+ "--hkm-mark-size": `${String(size)}px`,
521
+ ...mark === undefined || variant !== "tile" ? {} : {
522
+ "--hkm-mark-accent": mark.accent,
523
+ "--hkm-mark-ink": providerMarkOnAccent(mark)
524
+ }
525
+ };
526
+ if (mark === undefined) {
527
+ return /* @__PURE__ */ jsx("span", {
528
+ "aria-hidden": "true",
529
+ className: joinMockupClasses("hkm-brand-mark", className),
530
+ "data-hkm-monogram": "",
531
+ style,
532
+ children: providerMarkMonogram(name)
533
+ });
534
+ }
535
+ return /* @__PURE__ */ jsx("span", {
536
+ "aria-hidden": "true",
537
+ className: joinMockupClasses("hkm-brand-mark", className),
538
+ "data-hkm-mark": mark.id,
539
+ "data-hkm-variant": variant,
540
+ style,
541
+ children: /* @__PURE__ */ jsx("svg", {
542
+ dangerouslySetInnerHTML: {
543
+ __html: mark.glyph.body
544
+ },
545
+ fill: "currentColor",
546
+ focusable: "false",
547
+ viewBox: mark.glyph.viewBox
548
+ })
549
+ });
550
+ }
504
551
  function WindowLights() {
505
552
  return /* @__PURE__ */ jsxs("span", {
506
553
  "aria-hidden": "true",
@@ -513,4 +560,4 @@ function WindowLights() {
513
560
  });
514
561
  }
515
562
 
516
- export { joinMockupClasses, assertMockupDescription, MockupRoot, SampleText, SampleParagraphs, compact, mockupHash, mockupInitials, Avatar, PlaceholderPhoto, ScrollFade, Hotspot, mockupGlyphNames, MockupGlyph, WindowLights };
563
+ export { joinMockupClasses, assertMockupDescription, MockupRoot, SampleText, SampleParagraphs, compact, mockupHash, mockupInitials, Avatar, PlaceholderPhoto, ScrollFade, Hotspot, mockupGlyphNames, MockupGlyph, MockupBrandMark, WindowLights };