@clay-design-system/email 0.2.3 → 0.3.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 (195) hide show
  1. package/MIGRATION.md +31 -0
  2. package/README.md +7 -0
  3. package/dist/build/catalog.d.ts +0 -1
  4. package/dist/generated/email-tokens.d.ts +0 -1
  5. package/dist/generated/email-tokens.js +0 -1
  6. package/dist/index.d.ts +1 -2
  7. package/dist/index.js +0 -1
  8. package/package.json +14 -5
  9. package/dist/build/asset-scoring.d.ts +0 -48
  10. package/dist/build/asset-scoring.d.ts.map +0 -1
  11. package/dist/build/asset-scoring.js +0 -58
  12. package/dist/build/asset-scoring.js.map +0 -1
  13. package/dist/build/braze-transform.d.ts +0 -20
  14. package/dist/build/braze-transform.d.ts.map +0 -1
  15. package/dist/build/braze-transform.js +0 -26
  16. package/dist/build/braze-transform.js.map +0 -1
  17. package/dist/build/catalog.d.ts.map +0 -1
  18. package/dist/build/catalog.js +0 -3
  19. package/dist/build/catalog.js.map +0 -1
  20. package/dist/build/cloudinary-env.d.ts +0 -15
  21. package/dist/build/cloudinary-env.d.ts.map +0 -1
  22. package/dist/build/cloudinary-env.js +0 -36
  23. package/dist/build/cloudinary-env.js.map +0 -1
  24. package/dist/build/cloudinary-manifest.d.ts +0 -33
  25. package/dist/build/cloudinary-manifest.d.ts.map +0 -1
  26. package/dist/build/cloudinary-manifest.js +0 -36
  27. package/dist/build/cloudinary-manifest.js.map +0 -1
  28. package/dist/build/compile.d.ts +0 -11
  29. package/dist/build/compile.d.ts.map +0 -1
  30. package/dist/build/compile.js +0 -234
  31. package/dist/build/compile.js.map +0 -1
  32. package/dist/build/email-config.d.ts +0 -26
  33. package/dist/build/email-config.d.ts.map +0 -1
  34. package/dist/build/email-config.js +0 -17
  35. package/dist/build/email-config.js.map +0 -1
  36. package/dist/build/email-list.d.ts +0 -6
  37. package/dist/build/email-list.d.ts.map +0 -1
  38. package/dist/build/email-list.js +0 -17
  39. package/dist/build/email-list.js.map +0 -1
  40. package/dist/build/email-tree.d.ts +0 -23
  41. package/dist/build/email-tree.d.ts.map +0 -1
  42. package/dist/build/email-tree.js +0 -46
  43. package/dist/build/email-tree.js.map +0 -1
  44. package/dist/build/export-braze.d.ts +0 -22
  45. package/dist/build/export-braze.d.ts.map +0 -1
  46. package/dist/build/export-braze.js +0 -92
  47. package/dist/build/export-braze.js.map +0 -1
  48. package/dist/build/generate-stock-library-map.d.ts +0 -13
  49. package/dist/build/generate-stock-library-map.d.ts.map +0 -1
  50. package/dist/build/generate-stock-library-map.js +0 -202
  51. package/dist/build/generate-stock-library-map.js.map +0 -1
  52. package/dist/build/icon-registry-map.d.ts +0 -34
  53. package/dist/build/icon-registry-map.d.ts.map +0 -1
  54. package/dist/build/icon-registry-map.js +0 -44
  55. package/dist/build/icon-registry-map.js.map +0 -1
  56. package/dist/build/import-examples.d.ts +0 -14
  57. package/dist/build/import-examples.d.ts.map +0 -1
  58. package/dist/build/import-examples.js +0 -65
  59. package/dist/build/import-examples.js.map +0 -1
  60. package/dist/build/persona-character-map.d.ts +0 -32
  61. package/dist/build/persona-character-map.d.ts.map +0 -1
  62. package/dist/build/persona-character-map.js +0 -90
  63. package/dist/build/persona-character-map.js.map +0 -1
  64. package/dist/build/placeholder.d.ts +0 -79
  65. package/dist/build/placeholder.d.ts.map +0 -1
  66. package/dist/build/placeholder.js +0 -148
  67. package/dist/build/placeholder.js.map +0 -1
  68. package/dist/build/stock-library-map.d.ts +0 -57
  69. package/dist/build/stock-library-map.d.ts.map +0 -1
  70. package/dist/build/stock-library-map.js +0 -1261
  71. package/dist/build/stock-library-map.js.map +0 -1
  72. package/dist/build/upload-assets.d.ts +0 -20
  73. package/dist/build/upload-assets.d.ts.map +0 -1
  74. package/dist/build/upload-assets.js +0 -153
  75. package/dist/build/upload-assets.js.map +0 -1
  76. package/dist/build/upload-library-assets.d.ts +0 -21
  77. package/dist/build/upload-library-assets.d.ts.map +0 -1
  78. package/dist/build/upload-library-assets.js +0 -182
  79. package/dist/build/upload-library-assets.js.map +0 -1
  80. package/dist/build/visual-resolver.d.ts +0 -87
  81. package/dist/build/visual-resolver.d.ts.map +0 -1
  82. package/dist/build/visual-resolver.js +0 -439
  83. package/dist/build/visual-resolver.js.map +0 -1
  84. package/dist/examples/manifest.d.ts +0 -21
  85. package/dist/examples/manifest.d.ts.map +0 -1
  86. package/dist/examples/manifest.js +0 -84
  87. package/dist/examples/manifest.js.map +0 -1
  88. package/dist/exports/contact-sales/Images/Contact_sales_Image_16f4175c-d08c-43f6-9d4c-a0606383271d.png +0 -0
  89. package/dist/exports/contact-sales/Images/Contact_sales_Image_659b3091-1da9-40c2-86b0-04250982e529.png +0 -0
  90. package/dist/exports/contact-sales/Images/Contact_sales_Image_79c651f4-5f0f-4a7f-8354-1f6f95ae86d9.png +0 -0
  91. package/dist/exports/contact-sales/index.braze.html +0 -837
  92. package/dist/exports/contact-sales/index.html +0 -837
  93. package/dist/exports/event-confirmation/Images/Confirmation_Image_11938de2-4161-4ae8-8969-90ea0d8b45cb.png +0 -0
  94. package/dist/exports/event-confirmation/Images/Confirmation_Image_3c52e81f-5d4f-452c-bad1-0471a27598f1.png +0 -0
  95. package/dist/exports/event-confirmation/Images/Confirmation_Image_3ec1fec8-bf46-4068-8835-633567a715f9.png +0 -0
  96. package/dist/exports/event-confirmation/Images/Confirmation_Image_c4980c01-c270-4384-a56c-0bae74814cf9.png +0 -0
  97. package/dist/exports/event-confirmation/Images/Confirmation_Image_cde93e8c-0f96-434d-acaf-1b86503c66f0.png +0 -0
  98. package/dist/exports/event-confirmation/index.braze.html +0 -1055
  99. package/dist/exports/event-confirmation/index.html +0 -1055
  100. package/dist/exports/legal-update/Images/v2_Image_07bbcc13-0ab8-46e4-ab94-98f215f85f69.png +0 -0
  101. package/dist/exports/legal-update/Images/v2_Image_34394d50-acdf-4375-b254-eef1f84aaacb.png +0 -0
  102. package/dist/exports/legal-update/Images/v2_Image_4a25f2bd-6270-439b-86c5-4a968a1b104f.png +0 -0
  103. package/dist/exports/legal-update/Images/v2_Image_7e8e814f-3112-4d8c-af5b-4f4616d84d9c.png +0 -0
  104. package/dist/exports/legal-update/Images/v2_Image_b24a04c8-4af0-42a1-be0f-cd3f66595e47.png +0 -0
  105. package/dist/exports/legal-update/Images/v2_Image_b709b9fb-836e-4c20-82e5-a9cb9d702392.png +0 -0
  106. package/dist/exports/legal-update/Images/v2_Image_ed7b924b-35e6-4536-be0c-92ddc8a34fc2.png +0 -0
  107. package/dist/exports/legal-update/index.braze.html +0 -1731
  108. package/dist/exports/legal-update/index.html +0 -1731
  109. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_09be22f6-1f30-4c58-bf33-1df0494b8fc2.png +0 -0
  110. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_2dfb595e-6fe2-4e6e-a73a-942a085b38ab.png +0 -0
  111. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_544c971b-b4b5-4c89-a25a-8f0d92644009.png +0 -0
  112. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_5b6a9576-1c33-40c5-81e3-637514fb6c78.png +0 -0
  113. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_680c6193-793a-4a24-8288-4bb4046f4f5e.png +0 -0
  114. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_75818ba9-026a-45d7-91e4-f992d4ee7690.png +0 -0
  115. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_785f18e6-816d-44d1-8efb-ecc82510b540.png +0 -0
  116. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_8bf9141d-9d63-4601-9e81-5c9d726e17f8.png +0 -0
  117. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_9097d6e0-65d0-4237-9661-963751812786.png +0 -0
  118. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_a4ef2f53-2eaf-438a-bfef-61455ac0915e.png +0 -0
  119. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_b7748f87-a7b7-4a91-981a-16567683e4b4.png +0 -0
  120. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_bc9830a4-2911-4768-808a-32cbbc39215e.png +0 -0
  121. package/dist/exports/newsletter/Images/Status_update_-_July_26_Image_ef0e8e92-9075-43a9-991f-09a77ef6d6d4.png +0 -0
  122. package/dist/exports/newsletter/index.braze.html +0 -125
  123. package/dist/exports/newsletter/index.html +0 -125
  124. package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-blocks.png +0 -0
  125. package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-hero-mcp.png +0 -0
  126. package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-magic.png +0 -0
  127. package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-mcp.png +0 -0
  128. package/dist/exports/newsletter-ai-june-july/Images/newsletter-ai-portfolio.png +0 -0
  129. package/dist/exports/newsletter-ai-june-july/index.braze.html +0 -1640
  130. package/dist/exports/newsletter-ai-june-july/index.html +0 -1640
  131. package/dist/exports/survey/Images/EmailLove_Image_3b6f4a6f-7f5f-418b-be71-9371b25c20ce.png +0 -0
  132. package/dist/exports/survey/Images/EmailLove_Image_f659c728-2401-485d-8d90-98c962d28c0c.png +0 -0
  133. package/dist/exports/survey/index.braze.html +0 -515
  134. package/dist/exports/survey/index.html +0 -515
  135. package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Before_115ccc58-a47f-4eca-a1f2-c0d86e1e1cf4.png +0 -0
  136. package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Before_aec4d0d3-6057-4b8a-8d8f-46fbd024f182.png +0 -0
  137. package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Before_d139966a-6051-4383-bf8f-1e5138e1b030.png +0 -0
  138. package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Image_080fa361-a3f2-4593-9ac0-03cf3a7972ff.png +0 -0
  139. package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Image_5ebade34-8f1d-4c2c-9d27-5f9e843ce502.png +0 -0
  140. package/dist/exports/trial-01-welcome/Images/tp1_-_welcome_Image_aa5e4144-9ec8-4525-b01e-077d72f0bab6.png +0 -0
  141. package/dist/exports/trial-01-welcome/index.braze.html +0 -941
  142. package/dist/exports/trial-01-welcome/index.html +0 -941
  143. package/dist/exports/trial-02/Images/tp2_Image_5b0d9bc4-2e38-4252-8f20-d9f27d471c21.png +0 -0
  144. package/dist/exports/trial-02/Images/tp2_Image_b3f77c7c-cc8e-4db8-a5d9-072f4f621e72.png +0 -0
  145. package/dist/exports/trial-02/Images/tp2_Image_cafd1a17-1915-47cd-80f2-1c2d0b133cfe.png +0 -0
  146. package/dist/exports/trial-02/index.braze.html +0 -923
  147. package/dist/exports/trial-02/index.html +0 -923
  148. package/dist/exports/trial-03/Images/tp3_Image_1b96630c-fc4d-4aec-91fb-3c1d4d8544b3.png +0 -0
  149. package/dist/exports/trial-03/Images/tp3_Image_58f3a342-2193-4b5c-b30a-96f7f3338dd8.png +0 -0
  150. package/dist/exports/trial-03/Images/tp3_Image_6c4f307a-bac2-40e7-b4f1-9aa623c9eb8e.png +0 -0
  151. package/dist/exports/trial-03/Images/tp3_Image_848917ce-3f89-4538-a826-558b21f5fea7.png +0 -0
  152. package/dist/exports/trial-03/Images/tp3_Image_aae8410f-556f-4fb9-88f9-f276d75bafd2.png +0 -0
  153. package/dist/exports/trial-03/Images/tp3_Image_b4d5be39-509e-4f22-9601-dd070e4c6561.png +0 -0
  154. package/dist/exports/trial-03/index.braze.html +0 -1129
  155. package/dist/exports/trial-03/index.html +0 -1129
  156. package/dist/exports/trial-04/Images/tp4_Image_03bd5a56-25e3-4dcc-bef5-143bf12312d5.png +0 -0
  157. package/dist/exports/trial-04/Images/tp4_Image_0facbfca-b735-4199-a0d9-05a59341a1e3.gif +0 -0
  158. package/dist/exports/trial-04/Images/tp4_Image_171cee5f-cd3d-42f0-a180-995893d3742a.png +0 -0
  159. package/dist/exports/trial-04/Images/tp4_Image_3509d89d-1825-4817-8c1e-130fa294d0e1.png +0 -0
  160. package/dist/exports/trial-04/Images/tp4_Image_763a0f40-2985-4140-859b-ddd34f20a520.png +0 -0
  161. package/dist/exports/trial-04/Images/tp4_Image_cc2db4f5-b41d-45d7-a798-7a79e7b8d4d8.png +0 -0
  162. package/dist/exports/trial-04/index.braze.html +0 -885
  163. package/dist/exports/trial-04/index.html +0 -885
  164. package/dist/exports/trial-05/Images/tp5_Image_0248a517-5c60-4e84-ad1c-449dcf4f6a64.png +0 -0
  165. package/dist/exports/trial-05/Images/tp5_Image_4c1a2d5a-47d3-4801-bb3a-01c22decc108.png +0 -0
  166. package/dist/exports/trial-05/Images/tp5_Image_63ae77e7-cec7-4b4a-91e0-603b5a80929f.png +0 -0
  167. package/dist/exports/trial-05/Images/tp5_Image_7aa43530-6707-4308-ab0e-e4c38fc1b77d.png +0 -0
  168. package/dist/exports/trial-05/Images/tp5_Image_7efe5b6d-b360-4179-bee1-72908ba569bc.png +0 -0
  169. package/dist/exports/trial-05/Images/tp5_Image_b142bd84-c40a-4a29-b9d5-715b52fdd937.png +0 -0
  170. package/dist/exports/trial-05/Images/tp5_Image_c0c896ea-5b68-4f58-9e27-cdb4a1f1b438.png +0 -0
  171. package/dist/exports/trial-05/index.braze.html +0 -1023
  172. package/dist/exports/trial-05/index.html +0 -1023
  173. package/dist/exports/trial-06/Images/tp6_Image_2267a268-8a80-4e0d-8813-d4c75dbab6f2.png +0 -0
  174. package/dist/exports/trial-06/Images/tp6_Image_637a97b7-837e-478d-8ed1-6e8c2739fdc7.png +0 -0
  175. package/dist/exports/trial-06/Images/tp6_Image_a78df270-ad6f-41e6-8822-ba8ec38313a3.png +0 -0
  176. package/dist/exports/trial-06/index.braze.html +0 -773
  177. package/dist/exports/trial-06/index.html +0 -773
  178. package/dist/exports/winback/Images/_managers_Image_4587ac22-460c-487a-bc37-9dbc487e95a4.png +0 -0
  179. package/dist/exports/winback/Images/_managers_Image_8a77ec2c-ed49-480d-a1a1-7a38abad232a.png +0 -0
  180. package/dist/exports/winback/Images/_managers_Image_bb643775-8a2f-4e28-9dfb-6d1838c3561f.png +0 -0
  181. package/dist/exports/winback/Images/_managers_Image_f7d1bca5-0fcb-4d4c-abcd-40ce2d453b07.png +0 -0
  182. package/dist/exports/winback/index.braze.html +0 -605
  183. package/dist/exports/winback/index.html +0 -605
  184. package/dist/generated/email-tokens.d.ts.map +0 -1
  185. package/dist/generated/email-tokens.js.map +0 -1
  186. package/dist/index.d.ts.map +0 -1
  187. package/dist/index.js.map +0 -1
  188. package/dist/tokens/build-email-assets.d.ts +0 -19
  189. package/dist/tokens/build-email-assets.d.ts.map +0 -1
  190. package/dist/tokens/build-email-assets.js +0 -186
  191. package/dist/tokens/build-email-assets.js.map +0 -1
  192. package/dist/tokens/build-email-tokens.d.ts +0 -17
  193. package/dist/tokens/build-email-tokens.d.ts.map +0 -1
  194. package/dist/tokens/build-email-tokens.js +0 -229
  195. package/dist/tokens/build-email-tokens.js.map +0 -1
@@ -1,148 +0,0 @@
1
- /**
2
- * Labelled email placeholder generator (K10 EM-2).
3
- *
4
- * An unresolved image slot (visual-resolver.ts status 'placeholder') needs a visible stand-in while
5
- * the real asset is sourced. The shared `assets/placeholders/*.svg` tiles are blank and painted
6
- * #e6e7ea, which is not on the approved placeholder tint list, and SVG doesn't render in Outlook or
7
- * Gmail <img>. This module draws a **labelled** placeholder on an **approved tint** and writes it as
8
- * a 2× PNG campaign asset, so `email:upload` can host it like any other campaign image.
9
- *
10
- * The tint list mirrors `policy.email.color-system.image-placeholder-background-colors`
11
- * (19-email-color-system.md § Image Placeholder Background Colors); kb:test checks the two agree.
12
- *
13
- * Usage:
14
- * pnpm --filter @clay-design-system/email email:placeholder -- \
15
- * --label="A monday board built from a template" --size=560x320 \
16
- * [--tint=cool-grey|warm-cream|pale-blue|pale-lavender|pale-green|black] [--hero] [--scale=2] \
17
- * --out=<abs path>/src/assets/<campaign>/<name>.png (or .svg for the vector source)
18
- */
19
- import { mkdirSync, writeFileSync } from 'node:fs';
20
- import { dirname, resolve } from 'node:path';
21
- import { pathToFileURL } from 'node:url';
22
- import { emailColor, emailType } from '../generated/email-tokens';
23
- /** The approved placeholder background tints, in the order the colour-system policy lists them. */
24
- export const PLACEHOLDER_TINTS = {
25
- 'cool-grey': { hex: emailColor.page, use: 'Default — safe for any content type' },
26
- 'warm-cream': { hex: emailColor.surfaceWarm, use: 'Warm-tinted sections (surfaceWarm)' },
27
- 'pale-blue': { hex: '#eff5fd', use: 'Conference, webinar, event imagery' },
28
- 'pale-lavender': { hex: '#d9d7ff', use: 'Creative/design feature sections' },
29
- 'pale-green': { hex: '#ceead6', use: 'Sustainability, success, governance imagery' },
30
- black: { hex: emailColor.pageDark, use: 'Dark/dramatic hero image placeholder (above-fold hero only)' },
31
- };
32
- const MAX_LABEL = 120;
33
- function escapeXml(s) {
34
- return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;');
35
- }
36
- /** Greedy word wrap to `maxChars` per line, at most `maxLines` lines (the last one ellipsised). */
37
- export function wrapLabel(label, maxChars, maxLines) {
38
- const words = label.trim().split(/\s+/);
39
- const lines = [];
40
- let cur = '';
41
- for (const w of words) {
42
- const next = cur ? `${cur} ${w}` : w;
43
- if (next.length <= maxChars || !cur)
44
- cur = next;
45
- else {
46
- lines.push(cur);
47
- cur = w;
48
- }
49
- }
50
- if (cur)
51
- lines.push(cur);
52
- if (lines.length <= maxLines)
53
- return lines;
54
- const kept = lines.slice(0, maxLines);
55
- kept[maxLines - 1] = `${kept[maxLines - 1].replace(/[.,;:]?$/, '')}…`;
56
- return kept;
57
- }
58
- /** Validates the options; throws on anything the colour-system policy doesn't allow. */
59
- export function checkPlaceholderOptions(opts) {
60
- const tint = opts.tint ?? 'cool-grey';
61
- if (!(tint in PLACEHOLDER_TINTS)) {
62
- throw new Error(`Unknown placeholder tint "${tint}" — use one of ${Object.keys(PLACEHOLDER_TINTS).join(', ')} (policy.email.color-system.image-placeholder-background-colors)`);
63
- }
64
- if (tint === 'black' && !opts.hero)
65
- throw new Error('The black placeholder tint is for the above-fold hero only — pass hero: true (--hero), or use a pale tint');
66
- for (const [k, v] of [['width', opts.width], ['height', opts.height]]) {
67
- if (!Number.isInteger(v) || v < 16 || v > 1280)
68
- throw new Error(`Placeholder ${k} must be an integer display size in px (16–1280), got ${v}`);
69
- }
70
- const label = opts.label?.trim() ?? '';
71
- if (!label)
72
- throw new Error('A placeholder needs a label: say what the real image will show');
73
- if (label.length > MAX_LABEL)
74
- throw new Error(`Placeholder label is ${label.length} chars; keep it ≤${MAX_LABEL}`);
75
- return { width: opts.width, height: opts.height, label, tint, hero: !!opts.hero };
76
- }
77
- /** The labelled placeholder as an SVG string at display size (the PNG renders it at `scale`×). */
78
- export function placeholderSvg(opts) {
79
- const { width, height, label, tint } = checkPlaceholderOptions(opts);
80
- const bg = PLACEHOLDER_TINTS[tint].hex;
81
- const ink = tint === 'black' ? emailColor.textDark : emailColor.textMuted;
82
- const fontSize = Math.max(12, Math.min(24, Math.round(Math.min(width, height) / 12)));
83
- const sizeFont = Math.max(10, Math.round(fontSize * 0.7));
84
- const lineHeight = Math.round(fontSize * 1.3);
85
- const maxChars = Math.max(8, Math.floor((width * 0.84) / (fontSize * 0.56)));
86
- const maxLines = Math.max(1, Math.floor((height * 0.7 - sizeFont * 1.6) / lineHeight));
87
- const lines = wrapLabel(label, maxChars, maxLines);
88
- const blockH = lines.length * lineHeight + sizeFont * 1.6;
89
- const top = (height - blockH) / 2 + fontSize;
90
- const family = escapeXml(emailType.family);
91
- const text = lines
92
- .map((l, i) => `<text x="${width / 2}" y="${(top + i * lineHeight).toFixed(1)}" text-anchor="middle" font-family="${family}" font-size="${fontSize}" font-weight="600" fill="${ink}">${escapeXml(l)}</text>`)
93
- .join('');
94
- const sizeY = (top + lines.length * lineHeight + sizeFont * 0.4).toFixed(1);
95
- return (`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" role="img" aria-label="${escapeXml(`Placeholder: ${label}`)}">` +
96
- `<rect width="${width}" height="${height}" fill="${bg}"/>` +
97
- text +
98
- `<text x="${width / 2}" y="${sizeY}" text-anchor="middle" font-family="${family}" font-size="${sizeFont}" font-weight="400" fill="${ink}">${width}×${height} · placeholder</text>` +
99
- `</svg>`);
100
- }
101
- /** Writes the placeholder: `.svg` → the vector source; anything else → a `scale`× PNG (via sharp). */
102
- export async function writePlaceholder(opts) {
103
- const svg = placeholderSvg(opts);
104
- const out = resolve(opts.out);
105
- mkdirSync(dirname(out), { recursive: true });
106
- if (out.toLowerCase().endsWith('.svg')) {
107
- writeFileSync(out, svg);
108
- return { out, width: opts.width, height: opts.height };
109
- }
110
- const scale = opts.scale ?? 2;
111
- const { default: sharp } = await import('sharp');
112
- const png = await sharp(Buffer.from(svg), { density: 72 * scale })
113
- .resize(opts.width * scale, opts.height * scale)
114
- .png()
115
- .toBuffer();
116
- writeFileSync(out, png);
117
- return { out, width: opts.width * scale, height: opts.height * scale };
118
- }
119
- /** `--label=… --size=560x320 --tint=… --hero --scale=2 --out=…` → options. */
120
- export function parsePlaceholderArgs(argv) {
121
- const get = (k) => argv.find((a) => a.startsWith(`--${k}=`))?.slice(k.length + 3);
122
- const size = get('size') ?? '';
123
- const m = size.match(/^(\d+)x(\d+)$/);
124
- if (!m)
125
- throw new Error('--size=<width>x<height> (display px, e.g. 560x320) is required');
126
- const out = get('out');
127
- if (!out)
128
- throw new Error('--out=<path>.png (or .svg) is required — a campaign asset goes in src/assets/<campaign>/');
129
- return {
130
- width: Number(m[1]),
131
- height: Number(m[2]),
132
- label: get('label') ?? '',
133
- tint: get('tint') ?? 'cool-grey',
134
- hero: argv.includes('--hero'),
135
- scale: get('scale') ? Number(get('scale')) : undefined,
136
- out,
137
- };
138
- }
139
- const isMain = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
140
- if (isMain) {
141
- writePlaceholder(parsePlaceholderArgs(process.argv.slice(2)))
142
- .then((r) => console.log(`✓ placeholder ${r.width}×${r.height}px → ${r.out}`))
143
- .catch((err) => {
144
- console.error(`✗ ${err.message}`);
145
- process.exit(1);
146
- });
147
- }
148
- //# sourceMappingURL=placeholder.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../../src/build/placeholder.ts"],"names":[],"mappings":"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"}
@@ -1,57 +0,0 @@
1
- /**
2
- * GENERATED FILE — do not hand-edit. Regenerate via:
3
- * pnpm --filter @clay-design-system/email library:generate-map
4
- * Source: stock-library-source.csv (75 rows with a live cloudinary_url).
5
- *
6
- * The Cloudinary-hosted stock-image library (D5, board item Clay Lifecycle D5.5) — a tier
7
- * visual-resolver.ts can search when a visual-brief slot's intent names a specific scene this
8
- * bank already has (e.g. "Agile Dashboard with Kanban view"), before falling to a generic
9
- * placeholder. Committed as generated TS (not read live from Cloudinary) so
10
- * visual-resolver.test.ts stays CI-safe without live credentials — same reasoning as
11
- * persona-character-map.ts.
12
- */
13
- import { type RankedMatch, type SlotShape } from './asset-scoring';
14
- export interface StockLibraryEntry {
15
- /** Catalog id, e.g. "asset/agile-dashboard-overview-hero" — traces back to stock-library-source.csv. */
16
- id: string;
17
- slug: string;
18
- name: string;
19
- description: string;
20
- /** Slug words + tag_form/tag_context/use_case_domain — the stage-1 content-overlap vocabulary. */
21
- tags: string[];
22
- /** Raw tag_form column (e.g. 'card' | 'dashboard' | 'board-view' | 'exchange' | ...) — a stage-2 tie-breaker, independent of tags. */
23
- tagForm: string;
24
- /** Raw tag_context column (e.g. 'project' | 'campaign' | 'customer' | ...) — a stage-2 tie-breaker, independent of tags. */
25
- tagContext: string;
26
- useCaseDomain: string;
27
- /** Raw CSV width (px). Traceability + a stage-2 aspect signal via aspectRatioLabel, not scored directly. */
28
- width: number;
29
- /** Raw CSV height (px). */
30
- height: number;
31
- /** Raw CSV ratio column, verbatim: 'square' | 'wide' | 'super wide' — the stage-2 aspect-fit signal (see SHAPE_ACCEPTABLE_RATIOS). */
32
- aspectRatioLabel: string;
33
- /** Raw CSV local_file column. Traceability only, same status as description — never matched against. */
34
- localFile: string;
35
- /** Live Cloudinary secure_url, lifecycle/library/email-assets/<slug>. */
36
- cloudinaryUrl: string;
37
- /** Traceability back to the original Figma occurrence. */
38
- figmaSource: string;
39
- }
40
- export declare const STOCK_LIBRARY: StockLibraryEntry[];
41
- export interface StockLibraryMatchContext {
42
- intent: string;
43
- /** Derived automatically by visual-resolver.ts's deriveSlotShape — never hand-authored. */
44
- shape: SlotShape;
45
- /** Campaign slug, e.g. "sales-agent-activation" — scanned for a domain word alongside intent. */
46
- campaign?: string;
47
- }
48
- /**
49
- * Stage 1: score each entry by how many of its `tags` appear as whole words in `intent` — same
50
- * content-overlap rule as before. Stage 2 (only among entries tied for the max content score):
51
- * break the tie using aspect-ratio fit for the slot's shape, useCaseDomain, and literal
52
- * tag_form/tag_context matches — but only if that produces a single, strictly-positive winner.
53
- * A content tie that's still tied (or all-zero) on every secondary signal stays null, exactly as
54
- * before this module existed. See asset-scoring.ts's pickRankedMatch for the exact two-stage rule.
55
- */
56
- export declare function findStockLibraryEntry(ctx: StockLibraryMatchContext): RankedMatch<StockLibraryEntry> | null;
57
- //# sourceMappingURL=stock-library-map.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stock-library-map.d.ts","sourceRoot":"","sources":["../../src/build/stock-library-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAiC,KAAK,WAAW,EAA2B,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE1H,MAAM,WAAW,iBAAiB;IAChC,wGAAwG;IACxG,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,kGAAkG;IAClG,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,sIAAsI;IACtI,OAAO,EAAE,MAAM,CAAA;IACf,4HAA4H;IAC5H,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,4GAA4G;IAC5G,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,sIAAsI;IACtI,gBAAgB,EAAE,MAAM,CAAA;IACxB,wGAAwG;IACxG,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,aAAa,EAAE,MAAM,CAAA;IACrB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,iBAAiB,EAirC5C,CAAA;AAkBD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,2FAA2F;IAC3F,KAAK,EAAE,SAAS,CAAA;IAChB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,wBAAwB,GAAG,WAAW,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAqB1G"}