@clay-design-system/email 0.2.4 → 0.3.1

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,202 +0,0 @@
1
- /**
2
- * Generates stock-library-map.ts from stock-library-source.csv (D5.5, board item Clay Lifecycle D5).
3
- *
4
- * stock-library-source.csv is the authored source — same "CSV is authored, other artifacts are
5
- * generated from it, never hand-edit the generated file" convention as the Asset Catalog's own
6
- * CatalogTest.csv → chips_seed.sql (see .../Assets/Asset Catalog/Table/SCHEMA.md). This script is
7
- * the equivalent of that repo's `build_seed.py`.
8
- *
9
- * Usage:
10
- * pnpm --filter @clay-design-system/email library:generate-map
11
- */
12
- import { readFileSync, writeFileSync } from 'node:fs';
13
- import { dirname, resolve } from 'node:path';
14
- import { fileURLToPath } from 'node:url';
15
- const __dirname = dirname(fileURLToPath(import.meta.url));
16
- const SOURCE_CSV = resolve(__dirname, 'stock-library-source.csv');
17
- const OUT_TS = resolve(__dirname, 'stock-library-map.ts');
18
- /** Minimal RFC 4180 parser — handles quoted fields with embedded commas/newlines. Mirrors upload-library-assets.ts. */
19
- function parseCsv(text) {
20
- const rows = [];
21
- let field = '';
22
- let row = [];
23
- let inQuotes = false;
24
- for (let i = 0; i < text.length; i++) {
25
- const c = text[i];
26
- if (inQuotes) {
27
- if (c === '"') {
28
- if (text[i + 1] === '"') {
29
- field += '"';
30
- i++;
31
- }
32
- else {
33
- inQuotes = false;
34
- }
35
- }
36
- else
37
- field += c;
38
- }
39
- else if (c === '"')
40
- inQuotes = true;
41
- else if (c === ',') {
42
- row.push(field);
43
- field = '';
44
- }
45
- else if (c === '\n') {
46
- row.push(field);
47
- rows.push(row);
48
- row = [];
49
- field = '';
50
- }
51
- else if (c === '\r') { /* skip */ }
52
- else
53
- field += c;
54
- }
55
- if (field.length || row.length) {
56
- row.push(field);
57
- rows.push(row);
58
- }
59
- const [header, ...body] = rows.filter((r) => r.length > 1 || r[0] !== '');
60
- return body.map((r) => Object.fromEntries(header.map((h, idx) => [h, r[idx] ?? ''])));
61
- }
62
- const STOPWORDS = new Set(['a', 'an', 'the', 'and', 'or', 'of', 'in', 'on', 'for', 'with', 'to', 'its', 'this']);
63
- /** Slug words + tag_form/tag_context/use_case_domain — the vocabulary findStockLibraryEntry matches against. */
64
- function buildTags(row) {
65
- const slug = row.id.split('/', 2)[1];
66
- const slugWords = slug.split('-').filter((w) => w.length > 2 && !STOPWORDS.has(w));
67
- const facets = [row.tag_form, row.tag_context, row.use_case_domain]
68
- .filter(Boolean)
69
- .map((t) => t.toLowerCase());
70
- return [...new Set([...slugWords, ...facets])];
71
- }
72
- function tsStringLiteral(s) {
73
- return `'${s.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, ' ')}'`;
74
- }
75
- function main() {
76
- const rows = parseCsv(readFileSync(SOURCE_CSV, 'utf-8')).filter((r) => r.cloudinary_url);
77
- const entries = rows.map((r) => {
78
- const slug = r.id.split('/', 2)[1];
79
- const tags = buildTags(r);
80
- return ` {
81
- id: ${tsStringLiteral(r.id)},
82
- slug: ${tsStringLiteral(slug)},
83
- name: ${tsStringLiteral(r.name)},
84
- description: ${tsStringLiteral(r.description)},
85
- tags: [${tags.map(tsStringLiteral).join(', ')}],
86
- tagForm: ${tsStringLiteral(r.tag_form.toLowerCase())},
87
- tagContext: ${tsStringLiteral(r.tag_context.toLowerCase())},
88
- useCaseDomain: ${tsStringLiteral(r.use_case_domain)},
89
- width: ${Number(r.width) || 0},
90
- height: ${Number(r.height) || 0},
91
- aspectRatioLabel: ${tsStringLiteral(r.ratio.toLowerCase())},
92
- localFile: ${tsStringLiteral(r.local_file)},
93
- cloudinaryUrl: ${tsStringLiteral(r.cloudinary_url)},
94
- figmaSource: ${tsStringLiteral(r.figma_source)},
95
- }`;
96
- });
97
- const out = `/**
98
- * GENERATED FILE — do not hand-edit. Regenerate via:
99
- * pnpm --filter @clay-design-system/email library:generate-map
100
- * Source: stock-library-source.csv (${rows.length} rows with a live cloudinary_url).
101
- *
102
- * The Cloudinary-hosted stock-image library (D5, board item Clay Lifecycle D5.5) — a tier
103
- * visual-resolver.ts can search when a visual-brief slot's intent names a specific scene this
104
- * bank already has (e.g. "Agile Dashboard with Kanban view"), before falling to a generic
105
- * placeholder. Committed as generated TS (not read live from Cloudinary) so
106
- * visual-resolver.test.ts stays CI-safe without live credentials — same reasoning as
107
- * persona-character-map.ts.
108
- */
109
-
110
- import { containsWord, pickRankedMatch, type RankedMatch, SHAPE_ACCEPTABLE_RATIOS, type SlotShape } from './asset-scoring'
111
-
112
- export interface StockLibraryEntry {
113
- /** Catalog id, e.g. "asset/agile-dashboard-overview-hero" — traces back to stock-library-source.csv. */
114
- id: string
115
- slug: string
116
- name: string
117
- description: string
118
- /** Slug words + tag_form/tag_context/use_case_domain — the stage-1 content-overlap vocabulary. */
119
- tags: string[]
120
- /** Raw tag_form column (e.g. 'card' | 'dashboard' | 'board-view' | 'exchange' | ...) — a stage-2 tie-breaker, independent of tags. */
121
- tagForm: string
122
- /** Raw tag_context column (e.g. 'project' | 'campaign' | 'customer' | ...) — a stage-2 tie-breaker, independent of tags. */
123
- tagContext: string
124
- useCaseDomain: string
125
- /** Raw CSV width (px). Traceability + a stage-2 aspect signal via aspectRatioLabel, not scored directly. */
126
- width: number
127
- /** Raw CSV height (px). */
128
- height: number
129
- /** Raw CSV ratio column, verbatim: 'square' | 'wide' | 'super wide' — the stage-2 aspect-fit signal (see SHAPE_ACCEPTABLE_RATIOS). */
130
- aspectRatioLabel: string
131
- /** Raw CSV local_file column. Traceability only, same status as description — never matched against. */
132
- localFile: string
133
- /** Live Cloudinary secure_url, lifecycle/library/email-assets/<slug>. */
134
- cloudinaryUrl: string
135
- /** Traceability back to the original Figma occurrence. */
136
- figmaSource: string
137
- }
138
-
139
- export const STOCK_LIBRARY: StockLibraryEntry[] = [
140
- ${entries.join(',\n')},
141
- ]
142
-
143
- const KNOWN_DOMAINS = ['marketing', 'sales', 'it', 'pmo', 'hr', 'general', 'operations']
144
-
145
- /** Unambiguous-or-nothing, same rule as every other fuzzy matcher here — no scoring, no guessing. */
146
- function extractDomainHint(text: string): string | null {
147
- const lower = text.toLowerCase()
148
- const hits = KNOWN_DOMAINS.filter((d) => containsWord(lower, d))
149
- return hits.length === 1 ? hits[0] : null
150
- }
151
-
152
- // Placeholder weights — aspect is treated as the most structurally reliable secondary signal;
153
- // tune once real disambiguation behavior has been observed against production briefs.
154
- const W_ASPECT = 2
155
- const W_DOMAIN = 1
156
- const W_FORM = 1
157
- const W_CONTEXT = 1
158
-
159
- export interface StockLibraryMatchContext {
160
- intent: string
161
- /** Derived automatically by visual-resolver.ts's deriveSlotShape — never hand-authored. */
162
- shape: SlotShape
163
- /** Campaign slug, e.g. "sales-agent-activation" — scanned for a domain word alongside intent. */
164
- campaign?: string
165
- }
166
-
167
- /**
168
- * Stage 1: score each entry by how many of its \`tags\` appear as whole words in \`intent\` — same
169
- * content-overlap rule as before. Stage 2 (only among entries tied for the max content score):
170
- * break the tie using aspect-ratio fit for the slot's shape, useCaseDomain, and literal
171
- * tag_form/tag_context matches — but only if that produces a single, strictly-positive winner.
172
- * A content tie that's still tied (or all-zero) on every secondary signal stays null, exactly as
173
- * before this module existed. See asset-scoring.ts's pickRankedMatch for the exact two-stage rule.
174
- */
175
- export function findStockLibraryEntry(ctx: StockLibraryMatchContext): RankedMatch<StockLibraryEntry> | null {
176
- const lower = ctx.intent.toLowerCase()
177
- const domainHint = extractDomainHint(ctx.intent) ?? (ctx.campaign ? extractDomainHint(ctx.campaign) : null)
178
- const acceptableRatios = SHAPE_ACCEPTABLE_RATIOS[ctx.shape]
179
-
180
- return pickRankedMatch(STOCK_LIBRARY, {
181
- contentScore: (entry) => entry.tags.filter((tag) => containsWord(lower, tag)).length,
182
- secondaryScore: (entry) =>
183
- W_ASPECT * (acceptableRatios.has(entry.aspectRatioLabel) ? 1 : 0) +
184
- W_DOMAIN * (domainHint !== null && entry.useCaseDomain.toLowerCase() === domainHint ? 1 : 0) +
185
- W_FORM * (containsWord(lower, entry.tagForm) ? 1 : 0) +
186
- W_CONTEXT * (containsWord(lower, entry.tagContext) ? 1 : 0),
187
- explainSecondary: (entry) => {
188
- const reasons: string[] = []
189
- if (acceptableRatios.has(entry.aspectRatioLabel)) reasons.push('aspect:' + ctx.shape + '≈' + entry.aspectRatioLabel)
190
- if (domainHint !== null && entry.useCaseDomain.toLowerCase() === domainHint) reasons.push('domain:' + entry.useCaseDomain)
191
- if (containsWord(lower, entry.tagForm)) reasons.push('tagForm:' + entry.tagForm)
192
- if (containsWord(lower, entry.tagContext)) reasons.push('tagContext:' + entry.tagContext)
193
- return reasons
194
- },
195
- })
196
- }
197
- `;
198
- writeFileSync(OUT_TS, out);
199
- console.log(`Wrote ${entries.length} entries → ${OUT_TS}`);
200
- }
201
- main();
202
- //# sourceMappingURL=generate-stock-library-map.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-stock-library-map.js","sourceRoot":"","sources":["../../src/build/generate-stock-library-map.ts"],"names":[],"mappings":"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"}
@@ -1,34 +0,0 @@
1
- /**
2
- * Clay icon registry lookup for visual-resolver.ts tier 6 (D6, board item Clay Lifecycle D6).
3
- *
4
- * Reads packages/react/src/icons/icons.json at runtime (name/category/description/tags for all
5
- * ~600 Clay line icons) rather than importing it as a TS module — packages/email's tsconfig sets
6
- * rootDir: "src", so a cross-package relative TS import would violate it; a plain JSON file read
7
- * doesn't, same trick build-email-assets.ts already uses to reach
8
- * packages/react/src/icons/svg/*.svg for the actual SVG bytes. icons.json is itself generated by
9
- * the real Clay icon pipeline (scripts/docs/generate-icons.ts) — nothing here is invented.
10
- */
11
- import { type RankedMatch } from './asset-scoring';
12
- export interface IconRegistryEntry {
13
- name: string;
14
- category: string;
15
- description: string;
16
- tags: string[];
17
- /** Present only once scripts/cloudinary/upload-icons-to-cloudinary.ts has uploaded this icon. */
18
- cloudinarySvgUrl?: string;
19
- cloudinaryPngUrl?: string;
20
- }
21
- export declare const ICON_REGISTRY: IconRegistryEntry[];
22
- /** Exact name match — for an `icon` slot whose assetRef already names a real Clay icon. */
23
- export declare function findIconByName(name: string): IconRegistryEntry | null;
24
- /**
25
- * Stage 1: score each icon by how many of its tags appear as whole words in `intent` — same
26
- * content-overlap rule as before. Stage 2 (only among icons tied for the max content score):
27
- * break the tie by whether the icon's `category` appears as a whole word in `intent` — but only
28
- * if that produces a single, strictly-positive winner. A generic word like "check" still ties
29
- * dozens of icons on purpose, and same-category siblings (e.g. home-02/03/05, all "General") still
30
- * tie on category too — this never guesses between plausible candidates. See asset-scoring.ts's
31
- * pickRankedMatch for the exact two-stage rule.
32
- */
33
- export declare function findIconEntry(intent: string): RankedMatch<IconRegistryEntry> | null;
34
- //# sourceMappingURL=icon-registry-map.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icon-registry-map.d.ts","sourceRoot":"","sources":["../../src/build/icon-registry-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAiC,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAKjF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,iGAAiG;IACjG,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAOD,eAAO,MAAM,aAAa,EAAE,iBAAiB,EAAuB,CAAA;AAEpE,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAErE;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAOnF"}
@@ -1,44 +0,0 @@
1
- /**
2
- * Clay icon registry lookup for visual-resolver.ts tier 6 (D6, board item Clay Lifecycle D6).
3
- *
4
- * Reads packages/react/src/icons/icons.json at runtime (name/category/description/tags for all
5
- * ~600 Clay line icons) rather than importing it as a TS module — packages/email's tsconfig sets
6
- * rootDir: "src", so a cross-package relative TS import would violate it; a plain JSON file read
7
- * doesn't, same trick build-email-assets.ts already uses to reach
8
- * packages/react/src/icons/svg/*.svg for the actual SVG bytes. icons.json is itself generated by
9
- * the real Clay icon pipeline (scripts/docs/generate-icons.ts) — nothing here is invented.
10
- */
11
- import { existsSync, readFileSync } from 'node:fs';
12
- import { dirname, resolve } from 'node:path';
13
- import { fileURLToPath } from 'node:url';
14
- import { containsWord, pickRankedMatch } from './asset-scoring';
15
- const __dirname = dirname(fileURLToPath(import.meta.url));
16
- const ICONS_JSON = resolve(__dirname, '../../../../packages/react/src/icons/icons.json');
17
- function loadIconRegistry() {
18
- if (!existsSync(ICONS_JSON))
19
- return [];
20
- return JSON.parse(readFileSync(ICONS_JSON, 'utf-8'));
21
- }
22
- export const ICON_REGISTRY = loadIconRegistry();
23
- /** Exact name match — for an `icon` slot whose assetRef already names a real Clay icon. */
24
- export function findIconByName(name) {
25
- return ICON_REGISTRY.find((e) => e.name === name) ?? null;
26
- }
27
- /**
28
- * Stage 1: score each icon by how many of its tags appear as whole words in `intent` — same
29
- * content-overlap rule as before. Stage 2 (only among icons tied for the max content score):
30
- * break the tie by whether the icon's `category` appears as a whole word in `intent` — but only
31
- * if that produces a single, strictly-positive winner. A generic word like "check" still ties
32
- * dozens of icons on purpose, and same-category siblings (e.g. home-02/03/05, all "General") still
33
- * tie on category too — this never guesses between plausible candidates. See asset-scoring.ts's
34
- * pickRankedMatch for the exact two-stage rule.
35
- */
36
- export function findIconEntry(intent) {
37
- const lower = intent.toLowerCase();
38
- return pickRankedMatch(ICON_REGISTRY, {
39
- contentScore: (entry) => entry.tags.filter((tag) => containsWord(lower, tag)).length,
40
- secondaryScore: (entry) => (containsWord(lower, entry.category.toLowerCase()) ? 1 : 0),
41
- explainSecondary: (entry) => [`category:${entry.category}`],
42
- });
43
- }
44
- //# sourceMappingURL=icon-registry-map.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icon-registry-map.js","sourceRoot":"","sources":["../../src/build/icon-registry-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAoB,MAAM,iBAAiB,CAAA;AAEjF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,iDAAiD,CAAC,CAAA;AAYxF,SAAS,gBAAgB;IACvB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAA;IACtC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAwB,CAAA;AAC7E,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAwB,gBAAgB,EAAE,CAAA;AAEpE,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAA;AAC3D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAA;IAClC,OAAO,eAAe,CAAC,aAAa,EAAE;QACpC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM;QACpF,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtF,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,YAAY,KAAK,CAAC,QAAQ,EAAE,CAAC;KAC5D,CAAC,CAAA;AACJ,CAAC"}
@@ -1,14 +0,0 @@
1
- /**
2
- * One-off importer for real Email Love → Braze exports.
3
- *
4
- * These emails are NOT built from the DS MJML pipeline — they are finished exports from the
5
- * Email Love builder (a self-contained HTML file + a co-located `Images/` folder), kept in the
6
- * repo as reference artifacts of the desired output shape. This script normalizes each export
7
- * into `src/examples/<slug>/` with a flat `Images/` folder and an `index.html` whose image
8
- * references are collapsed to basenames, so the files resolve identically wherever they are served.
9
- *
10
- * Run once (or again to re-import after the source folder changes):
11
- * pnpm --filter @clay-design-system/email tsx src/build/import-examples.ts "<path to Lifecycle HTML examples>"
12
- */
13
- export {};
14
- //# sourceMappingURL=import-examples.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"import-examples.d.ts","sourceRoot":"","sources":["../../src/build/import-examples.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -1,65 +0,0 @@
1
- /**
2
- * One-off importer for real Email Love → Braze exports.
3
- *
4
- * These emails are NOT built from the DS MJML pipeline — they are finished exports from the
5
- * Email Love builder (a self-contained HTML file + a co-located `Images/` folder), kept in the
6
- * repo as reference artifacts of the desired output shape. This script normalizes each export
7
- * into `src/examples/<slug>/` with a flat `Images/` folder and an `index.html` whose image
8
- * references are collapsed to basenames, so the files resolve identically wherever they are served.
9
- *
10
- * Run once (or again to re-import after the source folder changes):
11
- * pnpm --filter @clay-design-system/email tsx src/build/import-examples.ts "<path to Lifecycle HTML examples>"
12
- */
13
- import { readdirSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, rmSync, existsSync, statSync, } from 'node:fs';
14
- import { resolve, join, dirname, basename, extname } from 'node:path';
15
- import { fileURLToPath } from 'node:url';
16
- import { EMAILS } from './email-list.js';
17
- const __dirname = dirname(fileURLToPath(import.meta.url));
18
- const examplesDir = resolve(__dirname, '..', 'examples');
19
- const DEFAULT_SOURCE = '/Users/eliorsi/Development/Landing pages Template/Lifecycle/Lifecycle HTML examples';
20
- const source = process.argv[2] ?? DEFAULT_SOURCE;
21
- const IMAGE_EXT = new Set(['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp']);
22
- /** Recursively collect all file paths under a directory. */
23
- function walk(dir) {
24
- const out = [];
25
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
26
- const full = join(dir, entry.name);
27
- if (entry.isDirectory())
28
- out.push(...walk(full));
29
- else
30
- out.push(full);
31
- }
32
- return out;
33
- }
34
- function importOne(slug, dir) {
35
- const srcDir = join(source, dir);
36
- if (!existsSync(srcDir))
37
- throw new Error(`Source folder not found: ${srcDir}`);
38
- const files = walk(srcDir);
39
- const htmlFile = files.find((f) => extname(f).toLowerCase() === '.html');
40
- if (!htmlFile)
41
- throw new Error(`No .html found under ${srcDir}`);
42
- const images = files.filter((f) => IMAGE_EXT.has(extname(f).toLowerCase()));
43
- const destDir = join(examplesDir, slug);
44
- const destImages = join(destDir, 'Images');
45
- rmSync(destDir, { recursive: true, force: true });
46
- mkdirSync(destImages, { recursive: true });
47
- for (const img of images)
48
- copyFileSync(img, join(destImages, basename(img)));
49
- // Collapse any `Images/<any/nested/path>/<file>.ext` reference down to `Images/<file>.ext`.
50
- let html = readFileSync(htmlFile, 'utf-8');
51
- html = html.replace(/(["'(])Images\/[^"')]*?([^/"')]+\.(?:png|jpe?g|gif|svg|webp))/gi, (_m, open, file) => `${open}Images/${file}`);
52
- writeFileSync(join(destDir, 'index.html'), html);
53
- const bytes = images.reduce((n, f) => n + statSync(f).size, 0);
54
- console.log(` ${slug.padEnd(18)} ${String(images.length).padStart(2)} images ` +
55
- `(${(bytes / 1024).toFixed(0)} KB) ← ${dir}`);
56
- }
57
- function main() {
58
- console.log(`Importing Email Love exports from:\n ${source}\n`);
59
- mkdirSync(examplesDir, { recursive: true });
60
- for (const { slug, dir } of EMAILS)
61
- importOne(slug, dir);
62
- console.log(`\nImported ${EMAILS.length} emails → ${examplesDir}`);
63
- }
64
- main();
65
- //# sourceMappingURL=import-examples.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"import-examples.js","sourceRoot":"","sources":["../../src/build/import-examples.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- /**
2
- * Persona/feature agent name → illustrated character, for standalone agent-portrait resolution
3
- * (visual-resolver.ts tier 1).
4
- *
5
- * Every entry here is sourced from something already committed to this repo — never invented.
6
- * Per `skills/campaign-brief/references/agents-catalog.md` rule 4: "the persona/avatar a reader
7
- * sees on the live card... IS the agent's identity... The brand asset bank supplies the artwork
8
- * only when it contains that character... never substitute a different bank character." That is
9
- * exactly why most entries below have `agentSlug: null` — the real character is documented, but
10
- * it has no illustration in packages/react/src/visuals/agents yet, and inventing a stand-in would
11
- * violate that rule. A `null` entry is not a smaller gap than an unknown name; visual-resolver.ts
12
- * still reports it as a `'gap'`, just a more specific one (the character is known, not missing).
13
- *
14
- * ⚠ Living table, not a permanent fact — agents-catalog.md itself warns the live library drifts
15
- * ("board ≠ live page names", agents renamed/added/removed). Re-verify against a fresh live
16
- * screenshot before trusting an entry for a new campaign; don't silently extend this list from
17
- * inference alone.
18
- */
19
- export interface PersonaCharacterEntry {
20
- /** Exact persona/feature name — must match the live library or MVP catalog board, never invented. */
21
- persona: string;
22
- /** The illustrated character shown on that persona's live card. */
23
- character: string;
24
- /** packages/react/src/visuals/agents AGENT_SLUGS key, only if that character is actually in the bank. */
25
- agentSlug: string | null;
26
- /** Where this pairing is documented/used in this repo. */
27
- source: string;
28
- }
29
- export declare const PERSONA_CHARACTER_MAP: PersonaCharacterEntry[];
30
- /** A single unambiguous persona match in the given text, or null if zero/multiple candidates match. */
31
- export declare function findPersonaEntry(text: string): PersonaCharacterEntry | null;
32
- //# sourceMappingURL=persona-character-map.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"persona-character-map.d.ts","sourceRoot":"","sources":["../../src/build/persona-character-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,qBAAqB;IACpC,qGAAqG;IACrG,OAAO,EAAE,MAAM,CAAA;IACf,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAA;IACjB,yGAAyG;IACzG,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,qBAAqB,EAAE,qBAAqB,EAgExD,CAAA;AAED,uGAAuG;AACvG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAO3E"}
@@ -1,90 +0,0 @@
1
- /**
2
- * Persona/feature agent name → illustrated character, for standalone agent-portrait resolution
3
- * (visual-resolver.ts tier 1).
4
- *
5
- * Every entry here is sourced from something already committed to this repo — never invented.
6
- * Per `skills/campaign-brief/references/agents-catalog.md` rule 4: "the persona/avatar a reader
7
- * sees on the live card... IS the agent's identity... The brand asset bank supplies the artwork
8
- * only when it contains that character... never substitute a different bank character." That is
9
- * exactly why most entries below have `agentSlug: null` — the real character is documented, but
10
- * it has no illustration in packages/react/src/visuals/agents yet, and inventing a stand-in would
11
- * violate that rule. A `null` entry is not a smaller gap than an unknown name; visual-resolver.ts
12
- * still reports it as a `'gap'`, just a more specific one (the character is known, not missing).
13
- *
14
- * ⚠ Living table, not a permanent fact — agents-catalog.md itself warns the live library drifts
15
- * ("board ≠ live page names", agents renamed/added/removed). Re-verify against a fresh live
16
- * screenshot before trusting an entry for a new campaign; don't silently extend this list from
17
- * inference alone.
18
- */
19
- export const PERSONA_CHARACTER_MAP = [
20
- {
21
- persona: 'Onboarding Program Manager',
22
- character: 'Sofia',
23
- agentSlug: 'sofia',
24
- source: 'skills/email-assets/knowledge/hero-masters-static.md (tp2a-onboarding-program-manager.html master); shipped in packages/email/src/emails/hr-trial-onboarding/tp2-first-agent',
25
- },
26
- {
27
- persona: 'Feature Request Agent',
28
- character: 'Zoe',
29
- agentSlug: 'zoe',
30
- source: 'skills/campaign-brief/references/agents-catalog.md, Product & Engineering section, live-verified 2026-08-03',
31
- },
32
- {
33
- persona: 'Outbound Prospector',
34
- character: 'Marco',
35
- agentSlug: null,
36
- source: 'skills/email-assets/knowledge/hero-masters-static.md ("Marco, Outbound Prospector"); shipped in packages/email/src/emails/sales-agent-activation/tp2a-outbound-prospector (Figma composite export, not AgentVisual)',
37
- },
38
- {
39
- persona: 'Pipeline Guardian',
40
- character: 'Noa',
41
- agentSlug: null,
42
- source: 'skills/email-assets/knowledge/hero-masters-static.md + hero-masters-carousel.md ("Noa, Pipeline Guardian"); shipped in packages/email/src/emails/sales-agent-activation/tp2b-pipeline-guardian (Figma composite export, not AgentVisual)',
43
- },
44
- {
45
- persona: 'Contract Renewal Agent',
46
- character: 'Enzo',
47
- agentSlug: null,
48
- source: 'skills/email-assets/knowledge/hero-masters-carousel.md ("Enzo" / "Contract Renewal Agent" card)',
49
- },
50
- {
51
- persona: 'Sprint Planner',
52
- character: 'Kobi',
53
- agentSlug: null,
54
- source: 'skills/campaign-brief/references/agents-catalog.md, Product & Engineering section, live-verified 2026-08-03',
55
- },
56
- {
57
- persona: 'Release Notes Agent',
58
- character: 'Clara',
59
- agentSlug: null,
60
- source: 'skills/campaign-brief/references/agents-catalog.md, Product & Engineering section, live-verified 2026-08-03',
61
- },
62
- {
63
- persona: 'PRD Writer & Keeper',
64
- character: 'Daniel',
65
- agentSlug: null,
66
- source: 'skills/campaign-brief/references/agents-catalog.md, Product & Engineering section, live-verified 2026-08-03',
67
- },
68
- {
69
- persona: 'Feedback Digest Agent',
70
- character: 'Jean',
71
- agentSlug: null,
72
- source: 'skills/campaign-brief/references/agents-catalog.md, Product & Engineering section, live-verified 2026-08-03',
73
- },
74
- {
75
- persona: 'Bug Triage Agent',
76
- character: 'Felix',
77
- agentSlug: null,
78
- source: 'skills/campaign-brief/references/agents-catalog.md, Product & Engineering section, live-verified 2026-08-03',
79
- },
80
- ];
81
- /** A single unambiguous persona match in the given text, or null if zero/multiple candidates match. */
82
- export function findPersonaEntry(text) {
83
- const lower = text.toLowerCase();
84
- const matches = PERSONA_CHARACTER_MAP.filter((entry) => {
85
- const escaped = entry.persona.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
86
- return new RegExp(`\\b${escaped}\\b`).test(lower);
87
- });
88
- return matches.length === 1 ? matches[0] : null;
89
- }
90
- //# sourceMappingURL=persona-character-map.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"persona-character-map.js","sourceRoot":"","sources":["../../src/build/persona-character-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAaH,MAAM,CAAC,MAAM,qBAAqB,GAA4B;IAC5D;QACE,OAAO,EAAE,4BAA4B;QACrC,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,OAAO;QAClB,MAAM,EACJ,8KAA8K;KACjL;IACD;QACE,OAAO,EAAE,uBAAuB;QAChC,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,KAAK;QAChB,MAAM,EAAE,6GAA6G;KACtH;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,IAAI;QACf,MAAM,EACJ,qNAAqN;KACxN;IACD;QACE,OAAO,EAAE,mBAAmB;QAC5B,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,IAAI;QACf,MAAM,EACJ,0OAA0O;KAC7O;IACD;QACE,OAAO,EAAE,wBAAwB;QACjC,SAAS,EAAE,MAAM;QACjB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,iGAAiG;KAC1G;IACD;QACE,OAAO,EAAE,gBAAgB;QACzB,SAAS,EAAE,MAAM;QACjB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,6GAA6G;KACtH;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,6GAA6G;KACtH;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,6GAA6G;KACtH;IACD;QACE,OAAO,EAAE,uBAAuB;QAChC,SAAS,EAAE,MAAM;QACjB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,6GAA6G;KACtH;IACD;QACE,OAAO,EAAE,kBAAkB;QAC3B,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,6GAA6G;KACtH;CACF,CAAA;AAED,uGAAuG;AACvG,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACrD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;QAClF,OAAO,IAAI,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IACF,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACjD,CAAC"}
@@ -1,79 +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
- /** The approved placeholder background tints, in the order the colour-system policy lists them. */
20
- export declare const PLACEHOLDER_TINTS: {
21
- readonly 'cool-grey': {
22
- readonly hex: "#f3f4f5";
23
- readonly use: "Default — safe for any content type";
24
- };
25
- readonly 'warm-cream': {
26
- readonly hex: "#f7f3ea";
27
- readonly use: "Warm-tinted sections (surfaceWarm)";
28
- };
29
- readonly 'pale-blue': {
30
- readonly hex: "#eff5fd";
31
- readonly use: "Conference, webinar, event imagery";
32
- };
33
- readonly 'pale-lavender': {
34
- readonly hex: "#d9d7ff";
35
- readonly use: "Creative/design feature sections";
36
- };
37
- readonly 'pale-green': {
38
- readonly hex: "#ceead6";
39
- readonly use: "Sustainability, success, governance imagery";
40
- };
41
- readonly black: {
42
- readonly hex: "#000000";
43
- readonly use: "Dark/dramatic hero image placeholder (above-fold hero only)";
44
- };
45
- };
46
- export type PlaceholderTint = keyof typeof PLACEHOLDER_TINTS;
47
- export interface PlaceholderOptions {
48
- /** Display width in px (the column the image sits in, e.g. 560). */
49
- width: number;
50
- /** Display height in px. */
51
- height: number;
52
- /** What the real image will show — printed on the tile, so a reviewer knows what's missing. */
53
- label: string;
54
- /** Default 'cool-grey'. */
55
- tint?: PlaceholderTint;
56
- /** The slot is the above-fold hero — the only slot that may use the black tint. */
57
- hero?: boolean;
58
- }
59
- /** Greedy word wrap to `maxChars` per line, at most `maxLines` lines (the last one ellipsised). */
60
- export declare function wrapLabel(label: string, maxChars: number, maxLines: number): string[];
61
- /** Validates the options; throws on anything the colour-system policy doesn't allow. */
62
- export declare function checkPlaceholderOptions(opts: PlaceholderOptions): Required<PlaceholderOptions>;
63
- /** The labelled placeholder as an SVG string at display size (the PNG renders it at `scale`×). */
64
- export declare function placeholderSvg(opts: PlaceholderOptions): string;
65
- /** Writes the placeholder: `.svg` → the vector source; anything else → a `scale`× PNG (via sharp). */
66
- export declare function writePlaceholder(opts: PlaceholderOptions & {
67
- out: string;
68
- scale?: number;
69
- }): Promise<{
70
- out: string;
71
- width: number;
72
- height: number;
73
- }>;
74
- /** `--label=… --size=560x320 --tint=… --hero --scale=2 --out=…` → options. */
75
- export declare function parsePlaceholderArgs(argv: string[]): PlaceholderOptions & {
76
- out: string;
77
- scale?: number;
78
- };
79
- //# sourceMappingURL=placeholder.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"placeholder.d.ts","sourceRoot":"","sources":["../../src/build/placeholder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,mGAAmG;AACnG,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;CAOpB,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,iBAAiB,CAAA;AAE5D,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,+FAA+F;IAC/F,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,mFAAmF;IACnF,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAQD,mGAAmG;AACnG,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBrF;AAED,wFAAwF;AACxF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,kBAAkB,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAa9F;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAwB/D;AAED,sGAAsG;AACtG,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAgB1J;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,kBAAkB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBzG"}