@samva/markup 0.8.0 → 0.10.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 (172) hide show
  1. package/AGENTS.md +107 -46
  2. package/CHANGELOG.md +345 -0
  3. package/README.md +188 -52
  4. package/dist/{brand-DcoVkh_S.d.ts → assets-BIsyMQ92.d.ts} +41 -11
  5. package/dist/{email/brand.js → brand-C0MKTwmX.js} +64 -4
  6. package/dist/{theme-css.d.ts → brand.d.ts} +12 -3
  7. package/dist/brand.js +4 -0
  8. package/dist/channel-specs-C2feJwuP.d.ts +13 -0
  9. package/dist/compiler.d.ts +88 -115
  10. package/dist/compiler.js +750 -171
  11. package/dist/components-BZCqegS8.js +1864 -0
  12. package/dist/diagnostic-model-DJtqbETd.js +38 -0
  13. package/dist/{diagnostics-OcQKQYSY.d.ts → diagnostic-model-DxthUZBT.d.ts} +3 -21
  14. package/dist/{diagnostics-BMYtBCQk.d.ts → diagnostics-B-Gym34R.d.ts} +8 -4
  15. package/dist/{email/diagnostics.js → diagnostics-CnKFefKz.js} +4 -3
  16. package/dist/diagnostics.d.ts +410 -2
  17. package/dist/diagnostics.js +402 -52
  18. package/dist/edit.d.ts +234 -0
  19. package/dist/edit.js +947 -0
  20. package/dist/email/jsx-dev-runtime.d.ts +2 -2
  21. package/dist/email/jsx-dev-runtime.js +1 -2
  22. package/dist/email/jsx-runtime.d.ts +1 -1
  23. package/dist/email/jsx-runtime.js +1 -85
  24. package/dist/{email/components.d.ts → email.d.ts} +22 -11
  25. package/dist/email.js +2 -0
  26. package/dist/fmt.d.ts +32 -0
  27. package/dist/fmt.js +174 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.js +2 -0
  30. package/dist/{render-vAv_4r9v.js → ir-CLhlklKV.js} +96 -279
  31. package/dist/jsx-runtime-CBlexoeR.js +98 -0
  32. package/dist/{elements-BzjjnoCS.d.ts → jsx-runtime-ylIOnaSf.d.ts} +76 -76
  33. package/dist/profile-pWGtWZXF.js +3803 -0
  34. package/dist/render-BPonDpCl.d.ts +539 -0
  35. package/dist/render-BQmfh94k.js +257 -0
  36. package/dist/render.d.ts +35 -0
  37. package/dist/render.js +49 -0
  38. package/dist/sms.d.ts +16 -0
  39. package/dist/sms.js +12 -0
  40. package/dist/source-locations-C8wCsiAy.d.ts +23 -0
  41. package/dist/template-DMPwxMSq.d.ts +65 -0
  42. package/dist/template-zLUjcwfF.js +42 -0
  43. package/dist/{theme-css-hFqcPSar.js → theme-css-JtRCm1fb.js} +2 -2
  44. package/dist/whatsapp.d.ts +57 -0
  45. package/dist/whatsapp.js +22 -0
  46. package/generated/contract.json +1788 -0
  47. package/generated/reference.md +360 -0
  48. package/package.json +46 -239
  49. package/samva-brand.d.ts +4 -4
  50. package/skills/sml/SKILL.md +123 -0
  51. package/dist/ast-BrDtApwS.d.ts +0 -107
  52. package/dist/ast.d.ts +0 -2
  53. package/dist/ast.js +0 -124
  54. package/dist/candidate.d.ts +0 -29
  55. package/dist/candidate.js +0 -88
  56. package/dist/catalog-CKuOooB8.d.ts +0 -354
  57. package/dist/checks-D73Xizbw.js +0 -59366
  58. package/dist/checks.d.ts +0 -33
  59. package/dist/checks.js +0 -2
  60. package/dist/classes.d.ts +0 -26
  61. package/dist/classes.js +0 -184
  62. package/dist/compile-sms.d.ts +0 -28
  63. package/dist/compile-sms.js +0 -44
  64. package/dist/compile-whatsapp.d.ts +0 -56
  65. package/dist/compile-whatsapp.js +0 -186
  66. package/dist/compile.d.ts +0 -18
  67. package/dist/compile.js +0 -29
  68. package/dist/components.d.ts +0 -289
  69. package/dist/components.js +0 -106
  70. package/dist/conditionals.d.ts +0 -10
  71. package/dist/conditionals.js +0 -74
  72. package/dist/corpus-CPPfgAHN.d.ts +0 -106
  73. package/dist/css-CS2jLID6.d.ts +0 -109
  74. package/dist/email/assets.d.ts +0 -40
  75. package/dist/email/assets.js +0 -63
  76. package/dist/email/brand-footer.d.ts +0 -34
  77. package/dist/email/brand-footer.js +0 -62
  78. package/dist/email/brand.d.ts +0 -2
  79. package/dist/email/components.js +0 -240
  80. package/dist/email/diagnostics.d.ts +0 -2
  81. package/dist/email/elements.d.ts +0 -2
  82. package/dist/email/elements.js +0 -299
  83. package/dist/email/html.d.ts +0 -2
  84. package/dist/email/html.js +0 -278
  85. package/dist/email/render.d.ts +0 -50
  86. package/dist/email/render.js +0 -3
  87. package/dist/email/selection.d.ts +0 -2
  88. package/dist/email/selection.js +0 -91
  89. package/dist/email/source-edit.d.ts +0 -67
  90. package/dist/email/source-edit.js +0 -185
  91. package/dist/email/stylesheets.d.ts +0 -15
  92. package/dist/email/stylesheets.js +0 -48
  93. package/dist/email/text.d.ts +0 -7
  94. package/dist/email/text.js +0 -100
  95. package/dist/emit.d.ts +0 -51
  96. package/dist/emit.js +0 -151
  97. package/dist/html-Bl9BAdqc.d.ts +0 -42
  98. package/dist/interpolate.d.ts +0 -24
  99. package/dist/interpolate.js +0 -43
  100. package/dist/jsx-dev-runtime.d.ts +0 -11
  101. package/dist/jsx-dev-runtime.js +0 -15
  102. package/dist/jsx-runtime-I-1nCtl2.d.ts +0 -57
  103. package/dist/jsx-runtime.d.ts +0 -2
  104. package/dist/jsx-runtime.js +0 -121
  105. package/dist/lexer.d.ts +0 -60
  106. package/dist/lexer.js +0 -281
  107. package/dist/model.d.ts +0 -24
  108. package/dist/model.js +0 -77
  109. package/dist/ops-BvwqHl7V.js +0 -630
  110. package/dist/ops.d.ts +0 -114
  111. package/dist/ops.js +0 -2
  112. package/dist/parser-t29cHLVL.d.ts +0 -396
  113. package/dist/parser.d.ts +0 -2
  114. package/dist/parser.js +0 -859
  115. package/dist/predicate-BI6uRRM-.js +0 -549
  116. package/dist/predicate-M-05Nd7R.d.ts +0 -56
  117. package/dist/predicate.d.ts +0 -2
  118. package/dist/predicate.js +0 -2
  119. package/dist/printer.d.ts +0 -6
  120. package/dist/printer.js +0 -122
  121. package/dist/registry-Dcp6QEK_.d.ts +0 -73
  122. package/dist/registry.d.ts +0 -2
  123. package/dist/registry.js +0 -646
  124. package/dist/render-template.d.ts +0 -45
  125. package/dist/render-template.js +0 -76
  126. package/dist/selection-CCArx9lU.d.ts +0 -91
  127. package/dist/showcase-egkusQBf.d.ts +0 -415
  128. package/dist/sms-segments-y4FpPilJ.d.ts +0 -13
  129. package/dist/sms-segments.d.ts +0 -2
  130. package/dist/sms-segments.js +0 -46
  131. package/dist/source-locations-DrCM82Ym.d.ts +0 -67
  132. package/dist/source-locations.d.ts +0 -2
  133. package/dist/source-locations.js +0 -102
  134. package/dist/starters/category-mapping.d.ts +0 -13
  135. package/dist/starters/category-mapping.js +0 -49
  136. package/dist/starters/corpus.d.ts +0 -2
  137. package/dist/starters/corpus.js +0 -194
  138. package/dist/starters/library.d.ts +0 -18
  139. package/dist/starters/library.js +0 -692
  140. package/dist/starters/public-gallery.d.ts +0 -266
  141. package/dist/starters/public-gallery.js +0 -916
  142. package/dist/starters/public-handoff.d.ts +0 -164
  143. package/dist/starters/public-handoff.js +0 -361
  144. package/dist/starters/public-preview-artifacts.d.ts +0 -43
  145. package/dist/starters/public-preview-artifacts.js +0 -104
  146. package/dist/starters/public-preview.d.ts +0 -61
  147. package/dist/starters/public-preview.js +0 -83
  148. package/dist/starters/showcase.d.ts +0 -2
  149. package/dist/starters/showcase.js +0 -335
  150. package/dist/starters/sources.d.ts +0 -45
  151. package/dist/starters/sources.js +0 -7762
  152. package/dist/starters/theme.d.ts +0 -45
  153. package/dist/starters/theme.js +0 -77
  154. package/dist/starters.d.ts +0 -2
  155. package/dist/starters.js +0 -874
  156. package/dist/tailwind-BYq7Lo6u.js +0 -727
  157. package/dist/template-DWftqh4x.d.ts +0 -60
  158. package/dist/template.d.ts +0 -2
  159. package/dist/template.js +0 -37
  160. package/dist/theme-css.js +0 -2
  161. package/dist/tsx-source-instrumentation.d.ts +0 -30
  162. package/dist/tsx-source-instrumentation.js +0 -115
  163. package/dist/tsx-tracer.d.ts +0 -112
  164. package/dist/tsx-tracer.js +0 -985
  165. package/dist/variables-J_L3qxRa.d.ts +0 -77
  166. package/dist/variables.d.ts +0 -2
  167. package/dist/variables.js +0 -141
  168. package/dist/version-BITr58kk.js +0 -96
  169. package/generated/sml-agent-contract.json +0 -709
  170. package/generated/sml-email-agent-contract.json +0 -615
  171. package/generated/sml-email-language-reference.md +0 -94
  172. package/generated/sml-language-reference.md +0 -195
package/dist/ast.js DELETED
@@ -1,124 +0,0 @@
1
- import { i as parsePredicate, n as collectPredicateVariables } from "./predicate-BI6uRRM-.js";
2
- import { Result } from "better-result";
3
- //#region src/ast.ts
4
- const BLOCK_TAGS = [
5
- "Email",
6
- "Subject",
7
- "Preview",
8
- "Container",
9
- "Section",
10
- "Row",
11
- "Column",
12
- "Heading",
13
- "Text",
14
- "Button",
15
- "Image",
16
- "Divider",
17
- "Spacer",
18
- "List",
19
- "ListItem",
20
- "If",
21
- "Else"
22
- ];
23
- const INLINE_TAGS = [
24
- "strong",
25
- "em",
26
- "a"
27
- ];
28
- /** Email-only helper tags scoped by their parent primitive. */
29
- const AUXILIARY_TAGS = ["Source"];
30
- /** Structured-channel tags: the sms/whatsapp vocabulary beyond shared If/Else. */
31
- const CHANNEL_TAGS = [
32
- "Sms",
33
- "WhatsApp",
34
- "Header",
35
- "Body",
36
- "Footer",
37
- "Buttons"
38
- ];
39
- const SML_TAGS = [
40
- ...BLOCK_TAGS,
41
- ...INLINE_TAGS,
42
- ...AUXILIARY_TAGS,
43
- ...CHANNEL_TAGS
44
- ];
45
- /**
46
- * JSX component name → the SML tag that component emits. TSX authors write
47
- * capitalized component names, and the inline tags are lowercase in SML, so
48
- * `<Strong>` emits `strong` and `<A>` emits `a`. The table is derived from
49
- * `SML_TAGS` rather than written out, so a new tag is mapped the moment it
50
- * joins the vocabulary. `components.ts` is held to it by the component test
51
- * suite, and `tsx-tracer.ts` resolves authored JSX names through it.
52
- */
53
- const SML_TAG_BY_COMPONENT_NAME = Object.freeze(Object.fromEntries(SML_TAGS.map((tag) => [`${tag[0].toUpperCase()}${tag.slice(1)}`, tag])));
54
- /** The SML tag a JSX component name emits, or `undefined` when it is not a Samva primitive. */
55
- const smlTagForComponentName = (name) => SML_TAG_BY_COMPONENT_NAME[name];
56
- /** The JSX component name that emits an SML tag, for printing SML back into TSX. */
57
- const componentNameForSmlTag = (tag) => `${tag[0].toUpperCase()}${tag.slice(1)}`;
58
- /** Resolved primary width for email documents that omit `<Email width={…}>`. */
59
- const DEFAULT_EMAIL_WIDTH = 600;
60
- /** Root tag → channel. The root tag IS the channel declaration. */
61
- const CHANNEL_BY_ROOT_TAG = {
62
- Email: "email",
63
- Sms: "sms",
64
- WhatsApp: "whatsapp"
65
- };
66
- const ROOT_TAGS = Object.keys(CHANNEL_BY_ROOT_TAG);
67
- const isRootTag = (tag) => tag in CHANNEL_BY_ROOT_TAG;
68
- /** The channel a parsed document targets, read off its root tag. */
69
- const documentChannel = (document) => CHANNEL_BY_ROOT_TAG[document.root.tag];
70
- const attributeValue = (node, name) => node.attributes.find((attribute) => attribute.name === name)?.value;
71
- const stringAttribute = (node, name) => {
72
- const value = attributeValue(node, name);
73
- return value?.kind === "string" ? value.value : void 0;
74
- };
75
- const numberAttribute = (node, name) => {
76
- const value = attributeValue(node, name);
77
- if (value === void 0) return void 0;
78
- return value.kind === "number" ? value.value : Number.parseInt(value.value, 10);
79
- };
80
- /**
81
- * The editor-only display label (navigator rename) — a universal attribute the
82
- * compiler never reads, so it never reaches HTML. Absent when unset.
83
- */
84
- const nodeLabel = (node) => stringAttribute(node, "label");
85
- /**
86
- * The editor-only visibility flag. A `hidden="true"` node stays in the source
87
- * (and the navigator, dimmed) but is dropped from every compile — preview and
88
- * send alike. Any other value / absence means visible.
89
- */
90
- const isHiddenNode = (node) => stringAttribute(node, "hidden") === "true";
91
- /**
92
- * All variable references in the document: `{{name}}` / `${name}` in children
93
- * and attribute values, plus names referenced by `<If test="...">` predicates.
94
- */
95
- const collectVariableReferences = (document) => {
96
- const names = /* @__PURE__ */ new Set();
97
- const attributePattern = /\$\{\s*\/?([\w.]+)\s*\}|\{\{\s*([\w.]+)\s*\}\}/g;
98
- const visit = (node) => {
99
- if (node.kind === "interpolation") {
100
- names.add(node.name);
101
- return;
102
- }
103
- if (node.kind === "text") return;
104
- for (const attribute of node.attributes) {
105
- if (attribute.value.kind !== "string") continue;
106
- if (node.tag === "If" && attribute.name === "test") {
107
- const parsed = parsePredicate(attribute.value.value);
108
- if (Result.isOk(parsed)) for (const name of collectPredicateVariables(parsed.value)) names.add(name);
109
- continue;
110
- }
111
- for (const match of attribute.value.value.matchAll(attributePattern)) {
112
- const name = match[1] ?? match[2];
113
- if (name !== void 0) names.add(name);
114
- }
115
- }
116
- for (const child of node.children) visit(child);
117
- };
118
- visit(document.root);
119
- return names;
120
- };
121
- //#endregion
122
- export { AUXILIARY_TAGS, BLOCK_TAGS, CHANNEL_BY_ROOT_TAG, CHANNEL_TAGS, DEFAULT_EMAIL_WIDTH, INLINE_TAGS, ROOT_TAGS, SML_TAGS, SML_TAG_BY_COMPONENT_NAME, attributeValue, collectVariableReferences, componentNameForSmlTag, documentChannel, isHiddenNode, isRootTag, nodeLabel, numberAttribute, smlTagForComponentName, stringAttribute };
123
-
124
- //# sourceMappingURL=ast.js.map
@@ -1,29 +0,0 @@
1
- //#region src/candidate.d.ts
2
- interface ParsedCandidate {
3
- readonly raw: string;
4
- /** Variant names in written order (validity is checked by the resolver). */
5
- readonly variants: ReadonlyArray<string>;
6
- /** root[-value] with variants/modifier/important stripped. */
7
- readonly base: string;
8
- /** Contents after the last `/` outside brackets, or null. */
9
- readonly modifier: string | null;
10
- /** Trailing `!`. */
11
- readonly important: boolean;
12
- }
13
- declare const parseCandidate: (raw: string) => ParsedCandidate;
14
- /**
15
- * Splits `base` into (root, value) against a known root set, preferring the
16
- * longest matching root ("max-w-lg" → root "max-w", not "max").
17
- * `value` is `null` for a bare root ("border", "rounded"),
18
- * `{ kind: "arbitrary" }` for `root-[...]`, else `{ kind: "named" }`.
19
- */
20
- declare const splitRoot: (base: string, roots: ReadonlySet<string>) => {
21
- readonly root: string;
22
- readonly value: {
23
- kind: "named" | "arbitrary";
24
- value: string;
25
- } | null;
26
- } | null;
27
- //#endregion
28
- export { ParsedCandidate, parseCandidate, splitRoot };
29
- //# sourceMappingURL=candidate.d.ts.map
package/dist/candidate.js DELETED
@@ -1,88 +0,0 @@
1
- //#region src/candidate.ts
2
- const splitOutsideBrackets = (value, separator) => {
3
- const parts = [];
4
- let depth = 0;
5
- let start = 0;
6
- for (let index = 0; index < value.length; index++) {
7
- const char = value[index];
8
- if (char === "[") depth++;
9
- else if (char === "]") depth = Math.max(0, depth - 1);
10
- else if (char === separator && depth === 0) {
11
- parts.push(value.slice(start, index));
12
- start = index + 1;
13
- }
14
- }
15
- parts.push(value.slice(start));
16
- return parts;
17
- };
18
- const parseCandidate = (raw) => {
19
- let rest = raw;
20
- const important = rest.endsWith("!");
21
- if (important) rest = rest.slice(0, -1);
22
- const segments = splitOutsideBrackets(rest, ":");
23
- const base = segments[segments.length - 1];
24
- const variants = segments.slice(0, -1);
25
- const lastSlash = (() => {
26
- let depth = 0;
27
- for (let index = base.length - 1; index >= 0; index--) {
28
- const char = base[index];
29
- if (char === "]") depth++;
30
- else if (char === "[") depth = Math.max(0, depth - 1);
31
- else if (char === "/" && depth === 0) return index;
32
- }
33
- return -1;
34
- })();
35
- if (lastSlash === -1) return {
36
- raw,
37
- variants,
38
- base,
39
- modifier: null,
40
- important
41
- };
42
- return {
43
- raw,
44
- variants,
45
- base: base.slice(0, lastSlash),
46
- modifier: base.slice(lastSlash + 1),
47
- important
48
- };
49
- };
50
- /**
51
- * Splits `base` into (root, value) against a known root set, preferring the
52
- * longest matching root ("max-w-lg" → root "max-w", not "max").
53
- * `value` is `null` for a bare root ("border", "rounded"),
54
- * `{ kind: "arbitrary" }` for `root-[...]`, else `{ kind: "named" }`.
55
- */
56
- const splitRoot = (base, roots) => {
57
- if (roots.has(base)) return {
58
- root: base,
59
- value: null
60
- };
61
- let dash = base.lastIndexOf("-");
62
- while (dash > 0) {
63
- const root = base.slice(0, dash);
64
- if (roots.has(root)) {
65
- const rawValue = base.slice(dash + 1);
66
- if (rawValue.startsWith("[") && rawValue.endsWith("]")) return {
67
- root,
68
- value: {
69
- kind: "arbitrary",
70
- value: rawValue.slice(1, -1)
71
- }
72
- };
73
- return {
74
- root,
75
- value: {
76
- kind: "named",
77
- value: rawValue
78
- }
79
- };
80
- }
81
- dash = base.lastIndexOf("-", dash - 1);
82
- }
83
- return null;
84
- };
85
- //#endregion
86
- export { parseCandidate, splitRoot };
87
-
88
- //# sourceMappingURL=candidate.js.map
@@ -1,354 +0,0 @@
1
- import { l as Channel } from "./ast-BrDtApwS.js";
2
- //#region starters/catalog.d.ts
3
- type StarterCategory = "transactional" | "digest" | "marketing" | "lifecycle";
4
- interface StarterMeta {
5
- /** Stable id and source filename stem (`${id}.tsx`). */
6
- readonly id: string;
7
- /** The source's root-tag channel; the gallery filters by it. */
8
- readonly channel: Channel;
9
- readonly category: StarterCategory;
10
- /** Human title for the gallery card. */
11
- readonly name: string;
12
- /** One-line description of when to reach for this starter. */
13
- readonly description: string;
14
- /**
15
- * Every input property declared by the template schema, sorted.
16
- * A sender supplies these values when rendering the template.
17
- */
18
- readonly variables: ReadonlyArray<string>;
19
- }
20
- declare const starterCatalog: readonly [{
21
- readonly id: "linear-login-code";
22
- readonly channel: "email";
23
- readonly category: "transactional";
24
- readonly name: "Linear login code";
25
- readonly description: "Recreate Linear's login code email with an editable magic link, code, and bundled logo.";
26
- readonly variables: readonly ["expiryNotice", "homeUrl", "loginUrl", "productName", "validationCode"];
27
- }, {
28
- readonly id: "product-newsletter";
29
- readonly channel: "email";
30
- readonly category: "digest";
31
- readonly name: "Product newsletter";
32
- readonly description: "A monthly product newsletter with a lead story, mapped secondary stories, a changelog and one action.";
33
- readonly variables: readonly ["changelog", "issueMonth", "issueNumber", "issueUrl", "leadImage", "leadSummary", "leadTitle", "leadUrl", "preferencesUrl", "stories", "unsubscribeUrl"];
34
- }, {
35
- readonly id: "vercel-invitation";
36
- readonly channel: "email";
37
- readonly category: "transactional";
38
- readonly name: "Vercel team invitation";
39
- readonly description: "Recreate Vercel's team invitation with editable source and bundled assets.";
40
- readonly variables: readonly ["inviteFromIp", "inviteFromLocation", "inviteLink", "invitedByEmail", "invitedByUsername", "teamImage", "teamName", "userImage", "username"];
41
- }, {
42
- readonly id: "order-receipt";
43
- readonly channel: "email";
44
- readonly category: "transactional";
45
- readonly name: "Order receipt";
46
- readonly description: "Itemized order receipt with product thumbnails, totals, payment summary and shipping address.";
47
- readonly variables: readonly ["customerName", "discount", "items", "orderDate", "orderNumber", "orderUrl", "paymentBrand", "paymentLast4", "shipping", "shippingAddress", "subtotal", "supportEmail", "tax", "total"];
48
- }, {
49
- readonly id: "welcome";
50
- readonly channel: "email";
51
- readonly category: "transactional";
52
- readonly name: "Welcome";
53
- readonly description: "First email after signup, with a lead illustration and a numbered list of first steps from the input.";
54
- readonly variables: readonly ["ctaUrl", "docsUrl", "firstName", "planNote", "steps", "supportEmail", "workspace"];
55
- }, {
56
- readonly id: "email-verification";
57
- readonly channel: "email";
58
- readonly category: "transactional";
59
- readonly name: "Email verification";
60
- readonly description: "Confirm a new email address with a one-click button, a fallback code and the request details behind it.";
61
- readonly variables: readonly ["email", "expiryNotice", "firstName", "previousEmail", "requestDetails", "supportEmail", "verificationCode", "verifyUrl", "workspace"];
62
- }, {
63
- readonly id: "otp";
64
- readonly channel: "email";
65
- readonly category: "transactional";
66
- readonly name: "One-time passcode";
67
- readonly description: "Deliver a short-lived sign-in code as the only thing on the page, with the request details under it.";
68
- readonly variables: readonly ["code", "expiryNotice", "helpUrl", "newDevice", "requestDetails", "workspace"];
69
- }, {
70
- readonly id: "password-reset";
71
- readonly channel: "email";
72
- readonly category: "transactional";
73
- readonly name: "Password reset";
74
- readonly description: "Send an expiring reset link with the request details, a paste-able fallback URL and an optional passkey offer.";
75
- readonly variables: readonly ["expiryNotice", "firstName", "passkeyPrompt", "requestDetails", "resetUrl", "securityUrl", "supportEmail", "workspace"];
76
- }, {
77
- readonly id: "payment-failed";
78
- readonly channel: "email";
79
- readonly category: "transactional";
80
- readonly name: "Payment failed";
81
- readonly description: "Declined-charge notice with the amount due, the card on file, the held order and every charge attempt.";
82
- readonly variables: readonly ["amountDue", "attempts", "automaticRetry", "customerName", "declineReason", "holdUntil", "items", "orderNumber", "paymentBrand", "paymentLast4", "supportEmail", "updatePaymentUrl"];
83
- }, {
84
- readonly id: "shipping-update";
85
- readonly channel: "email";
86
- readonly category: "transactional";
87
- readonly name: "Shipping update";
88
- readonly description: "Shipment notice with the carrier, tracking, delivery estimate, the packed items and anything still to come.";
89
- readonly variables: readonly ["carrier", "customerName", "estimatedDelivery", "items", "orderNumber", "pendingItems", "shippedDate", "shippingAddress", "supportEmail", "trackingNumber", "trackingUrl"];
90
- }, {
91
- readonly id: "notification";
92
- readonly channel: "email";
93
- readonly category: "transactional";
94
- readonly name: "Activity notification";
95
- readonly description: "Workspace activity notification with the actor, the message quoted in full, recent activity and a deep link back.";
96
- readonly variables: readonly ["actionSummary", "actorAvatar", "actorName", "attachment", "itemTitle", "itemUrl", "message", "otherActivity", "settingsUrl", "timestamp", "workspaceName"];
97
- }, {
98
- readonly id: "team-invite";
99
- readonly channel: "email";
100
- readonly category: "transactional";
101
- readonly name: "Team invite";
102
- readonly description: "Invite someone into a workspace with one accept action, the inviter's note and the people already there.";
103
- readonly variables: readonly ["acceptUrl", "expiryNotice", "inviteeEmail", "inviterAvatarUrl", "inviterEmail", "inviterName", "personalNote", "productName", "teammates", "workspace"];
104
- }, {
105
- readonly id: "data-sharing-review";
106
- readonly channel: "email";
107
- readonly category: "transactional";
108
- readonly name: "Data-sharing review";
109
- readonly description: "Ask a customer to keep or remove a third-party connection, listing every permission it holds.";
110
- readonly variables: readonly ["connectedServiceIconUrl", "connectedServiceName", "connectedSince", "keepConnectionUrl", "lastAccess", "recipientEmail", "referenceCode", "removeConnectionUrl", "scopes", "securityUrl", "settingsUrl", "workspace"];
111
- }, {
112
- readonly id: "product-digest";
113
- readonly channel: "email";
114
- readonly category: "digest";
115
- readonly name: "Weekly digest";
116
- readonly description: "A weekly reader digest: mapped stories with their desk and reading time, a most-read list, and an optional audio edition.";
117
- readonly variables: readonly ["archiveUrl", "editionLabel", "mostRead", "podcast", "preferencesUrl", "readerName", "stories", "unsubscribeUrl"];
118
- }, {
119
- readonly id: "editorial-newsletter";
120
- readonly channel: "email";
121
- readonly category: "digest";
122
- readonly name: "Long-form newsletter";
123
- readonly description: "A long-form editorial issue: a byline, an essay that renders from a list of paragraphs, a pull quote, an optional labelled sponsor and a reading list.";
124
- readonly variables: readonly ["authorAvatar", "authorName", "authorRole", "heroImage", "issueLabel", "paragraphs", "preferencesUrl", "pullQuote", "readingList", "sponsor", "standfirst", "storyUrl", "subscribeUrl", "title", "unsubscribeUrl"];
125
- }, {
126
- readonly id: "events-roundup";
127
- readonly channel: "email";
128
- readonly category: "digest";
129
- readonly name: "Events roundup";
130
- readonly description: "A dated events digest: an optional spotlight billing and a grid of upcoming shows with images, dates, rooms, prices and per-event tickets.";
131
- readonly variables: readonly ["calendarUrl", "cityName", "events", "helpUrl", "seasonLabel", "spotlight", "unsubscribeUrl"];
132
- }, {
133
- readonly id: "industry-news-digest";
134
- readonly channel: "email";
135
- readonly category: "digest";
136
- readonly name: "Industry news digest";
137
- readonly description: "A dense industry brief: an agenda, a lead story with details and analysis, mapped desk stories, an optional labelled sponsor, and tool and job lists.";
138
- readonly variables: readonly ["agenda", "audienceSize", "editionDate", "editionUrl", "intro", "jobs", "lead", "sponsor", "sponsorContactUrl", "stories", "tools", "unsubscribeUrl"];
139
- }, {
140
- readonly id: "announcement";
141
- readonly channel: "email";
142
- readonly category: "marketing";
143
- readonly name: "Feature announcement";
144
- readonly description: "Announce one change with a hero image, highlights from a list, an availability date and a single action.";
145
- readonly variables: readonly ["availableFrom", "ctaUrl", "featureDescription", "featureName", "featureTagline", "firstName", "highlights", "preferencesUrl", "releaseNoteUrl", "unsubscribeUrl"];
146
- }, {
147
- readonly id: "event-invite";
148
- readonly channel: "email";
149
- readonly category: "marketing";
150
- readonly name: "Event invite";
151
- readonly description: "Invite members to an event with the date, the place, an agenda from a list, and one RSVP action.";
152
- readonly variables: readonly ["agenda", "capacityNote", "declineUrl", "eventAddress", "eventDate", "eventDescription", "eventLocation", "eventName", "eventTagline", "eventTime", "firstName", "preferencesUrl", "rsvpUrl", "travelNote", "unsubscribeUrl"];
153
- }, {
154
- readonly id: "membership-promo";
155
- readonly channel: "email";
156
- readonly category: "marketing";
157
- readonly name: "Membership promotion";
158
- readonly description: "Promote a paid membership with tier cards from a list, a discount code, a deadline, and one join action.";
159
- readonly variables: readonly ["compareUrl", "discountPercent", "firstName", "headline", "joinUrl", "offerEnds", "preferencesUrl", "promoCode", "savingsNote", "subhead", "tiers", "unsubscribeUrl"];
160
- }, {
161
- readonly id: "member-referral-offer";
162
- readonly channel: "email";
163
- readonly category: "marketing";
164
- readonly name: "Member referral offer";
165
- readonly description: "Ask a member to bring people onto their account for a limited-time reward, with the steps and the terms as lists.";
166
- readonly variables: readonly ["firstName", "headline", "maxMembers", "maxReward", "offerEnds", "offerStarts", "preferencesUrl", "referralCode", "referralUrl", "reminderNote", "rewardPerMember", "spendMinimum", "steps", "subhead", "terms", "termsUrl", "unsubscribeUrl"];
167
- }, {
168
- readonly id: "catalog-sale-newsletter";
169
- readonly channel: "email";
170
- readonly category: "marketing";
171
- readonly name: "Catalog sale newsletter";
172
- readonly description: "Open a catalogue-wide sale with a bundle offer, a product grid from a list, a discount code, and the shop dates.";
173
- readonly variables: readonly ["bundleListPrice", "bundleName", "bundleSalePrice", "bundleUrl", "dates", "discountCode", "editionLabel", "editionYear", "firstName", "headline", "intro", "items", "offerEnds", "preferencesUrl", "shopUrl", "stockNote", "unsubscribeUrl"];
174
- }, {
175
- readonly id: "limited-time-savings";
176
- readonly channel: "email";
177
- readonly category: "marketing";
178
- readonly name: "Limited-time savings";
179
- readonly description: "A time-boxed savings offer with the hours remaining, reasons from a list, member quotes, and one claim action.";
180
- readonly variables: readonly ["claimUrl", "firstName", "headline", "hoursRemaining", "listPrice", "offerEnds", "postscript", "preferencesUrl", "promoCode", "reasons", "salePrice", "savingsAmount", "subhead", "testimonials", "timezoneUrl", "unsubscribeUrl"];
181
- }, {
182
- readonly id: "rewards-milestone";
183
- readonly channel: "email";
184
- readonly category: "marketing";
185
- readonly name: "Rewards milestone";
186
- readonly description: "Show a member how far through a rewards ladder they are, what the next step unlocks, and what each tier is worth.";
187
- readonly variables: readonly ["bonusNote", "expiresOn", "firstName", "headline", "milestoneLabel", "nextReward", "pointsBalance", "preferencesUrl", "rewardsUrl", "steps", "stepsCompleted", "stepsTotal", "subhead", "termsUrl", "tiers", "unsubscribeUrl"];
188
- }, {
189
- readonly id: "travel-rewards-promo";
190
- readonly channel: "email";
191
- readonly category: "marketing";
192
- readonly name: "Travel rewards promotion";
193
- readonly description: "A travel rewards promotion with a member balance, earning tiers from a list, and partner offers.";
194
- readonly variables: readonly ["accountUrl", "bookUrl", "firstName", "headline", "memberNumber", "milesBalance", "offerEnds", "partners", "preferencesUrl", "subhead", "termsUrl", "tierName", "tiers", "unsubscribeUrl"];
195
- }, {
196
- readonly id: "product-updates-roundup";
197
- readonly channel: "email";
198
- readonly category: "marketing";
199
- readonly name: "Product updates roundup";
200
- readonly description: "A monthly product roundup with a metrics strip, shipped updates from a list, and an optional event.";
201
- readonly variables: readonly ["changelogUrl", "event", "firstName", "headline", "intro", "issueMonth", "issueNumber", "metrics", "preferencesUrl", "unsubscribeUrl", "updates"];
202
- }, {
203
- readonly id: "flash-getaway-offer";
204
- readonly channel: "email";
205
- readonly category: "marketing";
206
- readonly name: "Flash getaway offer";
207
- readonly description: "A flash getaway offer with an input countdown, destinations from a list, and one booking action.";
208
- readonly variables: readonly ["countdown", "destinations", "exploreUrl", "firstName", "headline", "offerEnds", "offerWindow", "preferencesUrl", "subhead", "termsUrl", "unsubscribeUrl"];
209
- }, {
210
- readonly id: "membership-benefits-promo";
211
- readonly channel: "email";
212
- readonly category: "marketing";
213
- readonly name: "Membership benefits promotion";
214
- readonly description: "A paid-membership promotion with a price panel, benefits from a list, and one join action.";
215
- readonly variables: readonly ["benefits", "billingNote", "comparePlansUrl", "firstName", "headline", "joinUrl", "preferencesUrl", "priceLabel", "renewsOn", "subhead", "supportEmail", "trialLabel", "unsubscribeUrl"];
216
- }, {
217
- readonly id: "weekly-deals-circular";
218
- readonly channel: "email";
219
- readonly category: "marketing";
220
- readonly name: "Weekly deals circular";
221
- readonly description: "A weekly retail circular with deals from a list, clippable coupons, and one shop action.";
222
- readonly variables: readonly ["coupons", "deals", "headline", "intro", "memberPerk", "membershipUrl", "preferencesUrl", "shopUrl", "unsubscribeUrl", "validThrough", "weekLabel"];
223
- }, {
224
- readonly id: "seasonal-sale-flyer";
225
- readonly channel: "email";
226
- readonly category: "marketing";
227
- readonly name: "Seasonal sale flyer";
228
- readonly description: "A seasonal sale flyer with tiered promo codes, a category grid, and an optional gift-card offer.";
229
- readonly variables: readonly ["categories", "giftCard", "headline", "intro", "offerWindow", "preferencesUrl", "promoTiers", "seasonLabel", "shopUrl", "subhead", "termsUrl", "unsubscribeUrl"];
230
- }, {
231
- readonly id: "feature-release-roundup";
232
- readonly channel: "email";
233
- readonly category: "marketing";
234
- readonly name: "Feature release roundup";
235
- readonly description: "A feature release roundup with image-left rows from a list, release badges, and docs links.";
236
- readonly variables: readonly ["changelogUrl", "firstName", "headline", "intro", "migrationUrl", "preferencesUrl", "releases", "sunsetOn", "unsubscribeUrl"];
237
- }, {
238
- readonly id: "season-clearance-promo";
239
- readonly channel: "email";
240
- readonly category: "marketing";
241
- readonly name: "Season clearance promotion";
242
- readonly description: "A last-chance clearance promotion with marked-down highlights three a row and one shop action.";
243
- readonly variables: readonly ["deadlinePhrase", "firstName", "headline", "highlights", "intro", "newArrivalsUrl", "preferencesUrl", "remainingNote", "shopUrl", "unsubscribeUrl"];
244
- }, {
245
- readonly id: "product-launch-promo";
246
- readonly channel: "email";
247
- readonly category: "marketing";
248
- readonly name: "Product launch promotion";
249
- readonly description: "Launch a collection with a hero, a four-product grid, a discount code, and one shop action.";
250
- readonly variables: readonly ["bestSellersUrl", "discountCode", "firstName", "headline", "newArrivalsUrl", "offerEnds", "preferencesUrl", "products", "saleUrl", "shopUrl", "subhead", "unsubscribeUrl"];
251
- }, {
252
- readonly id: "onboarding-step";
253
- readonly channel: "email";
254
- readonly category: "lifecycle";
255
- readonly name: "Onboarding step";
256
- readonly description: "One step of an onboarding sequence, with the whole setup list, its progress, and a single next action.";
257
- readonly variables: readonly ["actionUrl", "docsUrl", "firstName", "stepBody", "stepNumber", "stepTitle", "steps", "supportEmail", "tip", "workspace"];
258
- }, {
259
- readonly id: "trial-ending";
260
- readonly channel: "email";
261
- readonly category: "lifecycle";
262
- readonly name: "Trial ending";
263
- readonly description: "Warn a trial user their access is ending, with what the trial produced, the plan that keeps it, and an optional offer.";
264
- readonly variables: readonly ["contactUrl", "daysLeft", "firstName", "highlights", "keeps", "offer", "plan", "trialEndDate", "upgradeUrl", "workspace"];
265
- }, {
266
- readonly id: "win-back";
267
- readonly channel: "email";
268
- readonly category: "lifecycle";
269
- readonly name: "Win-back";
270
- readonly description: "Re-engage a lapsed user with an illustrated list of what shipped while they were away, and an optional return offer.";
271
- readonly variables: readonly ["firstName", "lastActive", "offer", "preferencesUrl", "returnUrl", "unsubscribeUrl", "updates", "workspace"];
272
- }, {
273
- readonly id: "feedback-request";
274
- readonly channel: "email";
275
- readonly category: "lifecycle";
276
- readonly name: "Feedback request";
277
- readonly description: "Ask an active user one question with clickable answers, a short survey, and a named sender who reads the replies.";
278
- readonly variables: readonly ["firstName", "incentive", "options", "question", "sender", "surveyUrl", "tenure", "workspace"];
279
- }, {
280
- readonly id: "product-onboarding-tour";
281
- readonly channel: "email";
282
- readonly category: "lifecycle";
283
- readonly name: "Product onboarding tour";
284
- readonly description: "Walk a new user through the features worth turning on first, each with a still, its own points and a link, followed by a reading list.";
285
- readonly variables: readonly ["features", "firstName", "helpCenterUrl", "intro", "mobile", "preferencesUrl", "reads", "unsubscribeUrl"];
286
- }, {
287
- readonly id: "setup-checklist";
288
- readonly channel: "email";
289
- readonly category: "lifecycle";
290
- readonly name: "Setup checklist";
291
- readonly description: "Welcome a new customer with the setup steps that remain, each marked done or outstanding, and one link back into the flow.";
292
- readonly variables: readonly ["continueUrl", "firstName", "helpUrl", "note", "steps", "unsubscribeUrl", "welcome", "workspace"];
293
- }, {
294
- readonly id: "sms-otp";
295
- readonly channel: "sms";
296
- readonly category: "transactional";
297
- readonly name: "One-time passcode (SMS)";
298
- readonly description: "Deliver a short-lived sign-in or 2FA code in a single GSM-7 segment.";
299
- readonly variables: readonly ["code", "expiryMinutes", "workspace"];
300
- }, {
301
- readonly id: "sms-shipping-update";
302
- readonly channel: "sms";
303
- readonly category: "transactional";
304
- readonly name: "Shipping update (SMS)";
305
- readonly description: "Tell a customer their order shipped, with a tracking link.";
306
- readonly variables: readonly ["orderNumber", "trackingUrl", "workspace"];
307
- }, {
308
- readonly id: "sms-appointment-reminder";
309
- readonly channel: "sms";
310
- readonly category: "lifecycle";
311
- readonly name: "Appointment reminder (SMS)";
312
- readonly description: "Remind a customer of an upcoming appointment with a reschedule path.";
313
- readonly variables: readonly ["appointmentDate", "appointmentTime", "workspace"];
314
- }, {
315
- readonly id: "sms-flash-sale";
316
- readonly channel: "sms";
317
- readonly category: "marketing";
318
- readonly name: "Flash sale (SMS)";
319
- readonly description: "Drive a limited-time offer with a promo code and a conditional urgency line.";
320
- readonly variables: readonly ["endsToday", "offerHeadline", "promoCode", "shopUrl", "workspace"];
321
- }, {
322
- readonly id: "whatsapp-order-update";
323
- readonly channel: "whatsapp";
324
- readonly category: "transactional";
325
- readonly name: "Order update (WhatsApp)";
326
- readonly description: "Utility template: shipping confirmation with a tracking URL button.";
327
- readonly variables: readonly ["estimatedDelivery", "firstName", "orderNumber", "trackingUrl"];
328
- }, {
329
- readonly id: "whatsapp-appointment-reminder";
330
- readonly channel: "whatsapp";
331
- readonly category: "lifecycle";
332
- readonly name: "Appointment reminder (WhatsApp)";
333
- readonly description: "Utility template: appointment reminder with confirm/reschedule quick replies.";
334
- readonly variables: readonly ["appointmentDate", "appointmentTime", "firstName", "workspace"];
335
- }, {
336
- readonly id: "whatsapp-flash-sale";
337
- readonly channel: "whatsapp";
338
- readonly category: "marketing";
339
- readonly name: "Flash sale (WhatsApp)";
340
- readonly description: "Marketing template: limited-time offer with a copyable promo code and a shop button.";
341
- readonly variables: readonly ["endsToday", "firstName", "offerDetails", "offerHeadline", "promoCode", "shopUrl"];
342
- }];
343
- type StarterId = (typeof starterCatalog)[number]["id"];
344
- type StarterVariable = (typeof starterCatalog)[number]["variables"][number];
345
- type EmailStarter = Extract<(typeof starterCatalog)[number], {
346
- channel: "email";
347
- }>;
348
- type EmailStarterId = EmailStarter["id"];
349
- type EmailStarterVariable = EmailStarter extends (infer Starter) ? Starter extends {
350
- readonly variables: ReadonlyArray<infer Variable>;
351
- } ? Variable : never : never;
352
- //#endregion
353
- export { StarterMeta as a, StarterId as i, EmailStarterVariable as n, StarterVariable as o, StarterCategory as r, starterCatalog as s, EmailStarterId as t };
354
- //# sourceMappingURL=catalog-CKuOooB8.d.ts.map