@samva/markup 0.2.0 → 0.4.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.
@@ -1,12 +1,19 @@
1
1
  import { d as Channel } from "../ast-63I-VLQx.js";
2
- import { PresetCategory } from "../presets.js";
2
+ import { r as PresetCategory } from "../catalog-Ck1tAGwO.js";
3
3
  import { TemplateCollectionId, TemplateUseCase } from "./public-gallery.js";
4
4
  import { PublicTemplatePreview } from "./public-preview.js";
5
+ import { PresetProject } from "./sources.js";
5
6
  import { Result } from "effect";
6
7
  //#region presets/public-handoff.d.ts
8
+ /** The brand a clean-room recreation names, and what its email does. */
9
+ interface TemplateBrandRecreation {
10
+ readonly brand: string;
11
+ readonly subject: string;
12
+ }
7
13
  /** Where an approved public artifact came from. */
8
14
  interface TemplateReferenceProvenance {
9
- readonly source: "samva-owned" | "sanitized-synthetic" | "reviewed-public";
15
+ readonly source: "samva-owned" | "sanitized-synthetic" | "reviewed-public" | "brand-recreation";
16
+ readonly brandRecreation?: TemplateBrandRecreation;
10
17
  /** Stable identifier in the producing system; never a third-party URL. */
11
18
  readonly referenceId: string;
12
19
  /** Stable ISO-8601 timestamp supplied by the producer. */
@@ -27,6 +34,7 @@ interface ApprovedPublicTemplateArtifact {
27
34
  readonly description: string;
28
35
  readonly variables: ReadonlyArray<string>;
29
36
  readonly source: string;
37
+ readonly project?: PresetProject;
30
38
  };
31
39
  readonly gallery: {
32
40
  readonly slug: string;
@@ -62,8 +70,9 @@ interface TemplateReferencePacket {
62
70
  readonly provenance: TemplateReferenceProvenance;
63
71
  }
64
72
  interface ValidatedPublicTemplateArtifact {
65
- readonly preset: Omit<ApprovedPublicTemplateArtifact["preset"], "source">;
73
+ readonly preset: Omit<ApprovedPublicTemplateArtifact["preset"], "source" | "project">;
66
74
  readonly source: string;
75
+ readonly project?: PresetProject;
67
76
  readonly gallery: ApprovedPublicTemplateArtifact["gallery"] & {
68
77
  readonly path: `/templates/${string}`;
69
78
  };
@@ -82,6 +91,16 @@ interface PublicHandoffIssue {
82
91
  }
83
92
  /** Bound authored source before parsing or mounting it. */
84
93
  declare const PUBLIC_TEMPLATE_SOURCE_MAX_CHARACTERS = 512000;
94
+ /** Bounds apply to decoded bytes, before evaluation or disk emission. */
95
+ declare const PUBLIC_TEMPLATE_PROJECT_MAX_BYTES: number;
96
+ declare const PUBLIC_TEMPLATE_PROJECT_FILE_MAX_BYTES: number;
97
+ declare const PUBLIC_TEMPLATE_PROJECT_MAX_FILES = 64;
98
+ declare const isSafePublicTemplateProjectPath: (path: string) => boolean;
99
+ /** Reject traversal, collisions, malformed base64 and oversized authored projects. */
100
+ declare const isSafePublicTemplateProject: (project: PresetProject) => boolean;
101
+ /** Digest the complete authored graph independently of caller file ordering. */
102
+ declare const publicTemplateProjectDigest: (project: Pick<PresetProject, "entryPath" | "files">) => Promise<string>;
103
+ declare const isValidTemplateBrandRecreation: (brandRecreation: TemplateBrandRecreation | undefined, project: PresetProject | undefined) => boolean;
85
104
  /** Static syntax inventory; loops, branches and component expansion are not evaluated. */
86
105
  interface PublicTemplateAuthoredStructure {
87
106
  readonly basis: "authored-jsx";
@@ -117,12 +136,17 @@ type TemplateReferenceProjection = {
117
136
  readonly relativePath: "preset.tsx";
118
137
  readonly contents: string;
119
138
  } | {
120
- readonly kind: "catalog" | "gallery" | "preview" | "editorial";
121
- readonly relativePath: `${"catalog" | "gallery" | "preview" | "editorial"}.json`;
139
+ readonly kind: "project-file";
140
+ readonly relativePath: `project/${string}`;
141
+ readonly contents: string;
142
+ readonly encoding: "utf8" | "base64";
143
+ } | {
144
+ readonly kind: "catalog" | "gallery" | "preview" | "editorial" | "project";
145
+ readonly relativePath: `${"catalog" | "gallery" | "preview" | "editorial" | "project"}.json`;
122
146
  readonly contents: string;
123
147
  };
124
148
  /**
125
- * Emits the five destination projections as deterministic bytes. The importer
149
+ * Emits legacy projections plus the complete project as deterministic bytes. The importer
126
150
  * owns no checked-in destination files; callers choose an explicit output dir.
127
151
  */
128
152
  declare const emitTemplateReferencePacket: (packet: TemplateReferencePacket) => ReadonlyArray<TemplateReferenceProjection>;
@@ -136,5 +160,5 @@ declare const emitTemplateReferencePacket: (packet: TemplateReferencePacket) =>
136
160
  */
137
161
  declare const validatePublicTemplateHandoff: (artifacts: ReadonlyArray<ApprovedPublicTemplateArtifact>) => Result.Result<ReadonlyArray<ValidatedPublicTemplateArtifact>, ReadonlyArray<PublicHandoffIssue>>;
138
162
  //#endregion
139
- export { ApprovedPublicTemplateArtifact, PUBLIC_TEMPLATE_SOURCE_MAX_CHARACTERS, PublicHandoffIssue, PublicHandoffIssueCode, PublicTemplateAuthoredStructure, TemplateReferencePacket, TemplateReferenceProjection, TemplateReferenceProvenance, ValidatedPublicTemplateArtifact, emitTemplateReferencePacket, isSafePublicTemplateAsset, publicTemplateAuthoredStructure, toTemplateReferencePacket, unsupportedPublicTemplateFontTokens, validatePublicTemplateHandoff };
163
+ export { ApprovedPublicTemplateArtifact, PUBLIC_TEMPLATE_PROJECT_FILE_MAX_BYTES, PUBLIC_TEMPLATE_PROJECT_MAX_BYTES, PUBLIC_TEMPLATE_PROJECT_MAX_FILES, PUBLIC_TEMPLATE_SOURCE_MAX_CHARACTERS, PublicHandoffIssue, PublicHandoffIssueCode, PublicTemplateAuthoredStructure, TemplateBrandRecreation, TemplateReferencePacket, TemplateReferenceProjection, TemplateReferenceProvenance, ValidatedPublicTemplateArtifact, emitTemplateReferencePacket, isSafePublicTemplateAsset, isSafePublicTemplateProject, isSafePublicTemplateProjectPath, isValidTemplateBrandRecreation, publicTemplateAuthoredStructure, publicTemplateProjectDigest, toTemplateReferencePacket, unsupportedPublicTemplateFontTokens, validatePublicTemplateHandoff };
140
164
  //# sourceMappingURL=public-handoff.d.ts.map
@@ -11,9 +11,62 @@ const MAX_DATA_IMAGE_ASSET_LENGTH = 32768;
11
11
  const DATA_IMAGE = /^data:image\/(?:avif|gif|jpeg|png|svg\+xml|webp)(?:;charset=[a-z0-9-]+)?(?:;base64)?,[^\r\n]+$/i;
12
12
  const PUBLIC_TEMPLATE_ASSET_PATH = /^\/templates\/assets\/[A-Za-z0-9][A-Za-z0-9._-]*\.(?:jpe?g|png|webp)$/;
13
13
  const BLOCKED_PUBLIC_ASSET = /(?:unsplash|placehold|assets\.example)/i;
14
- const isTemplateReferenceProvenanceSource = (value) => value === "samva-owned" || value === "sanitized-synthetic" || value === "reviewed-public";
14
+ /** A sample value is non-empty when every string in it is, and no list or object is empty. */
15
+ const nonEmptySample = (value) => {
16
+ if (typeof value === "string") return nonEmpty(value);
17
+ if (Array.isArray(value)) return value.length > 0 && value.every(nonEmptySample);
18
+ if (Predicate.isObject(value)) {
19
+ const values = Object.values(value);
20
+ return values.length > 0 && values.every(nonEmptySample);
21
+ }
22
+ return true;
23
+ };
24
+ const isTemplateReferenceProvenanceSource = (value) => value === "samva-owned" || value === "sanitized-synthetic" || value === "reviewed-public" || value === "brand-recreation";
15
25
  /** Bound authored source before parsing or mounting it. */
16
26
  const PUBLIC_TEMPLATE_SOURCE_MAX_CHARACTERS = 512e3;
27
+ /** Bounds apply to decoded bytes, before evaluation or disk emission. */
28
+ const PUBLIC_TEMPLATE_PROJECT_MAX_BYTES = 8388608;
29
+ const PUBLIC_TEMPLATE_PROJECT_FILE_MAX_BYTES = 2097152;
30
+ const PUBLIC_TEMPLATE_PROJECT_MAX_FILES = 64;
31
+ const isSafePublicTemplateProjectPath = (path) => path.length <= 240 && path.split("/").every((part) => /^[A-Za-z0-9_][A-Za-z0-9._-]*$/.test(part) && part !== "." && part !== ".." && part !== "node_modules");
32
+ /** Reject traversal, collisions, malformed base64 and oversized authored projects. */
33
+ const isSafePublicTemplateProject = (project) => {
34
+ if (!isSafePublicTemplateProjectPath(project.entryPath) || !project.entryPath.endsWith(".tsx") || !/^[a-f0-9]{64}$/.test(project.digest) || project.files.length === 0 || project.files.length > 64) return false;
35
+ const paths = /* @__PURE__ */ new Set();
36
+ let total = 0;
37
+ for (const file of project.files) {
38
+ if (!isSafePublicTemplateProjectPath(file.path) || paths.has(file.path.toLowerCase())) return false;
39
+ paths.add(file.path.toLowerCase());
40
+ let bytes;
41
+ if (file.encoding === "utf8") {
42
+ if (file.content.length > 512e3) return false;
43
+ bytes = new TextEncoder().encode(file.content).length;
44
+ } else if (file.encoding === "base64") {
45
+ if (file.content.length > Math.ceil(2097152 / 3) * 4 || file.content.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(file.content)) return false;
46
+ if (btoa(atob(file.content)) !== file.content) return false;
47
+ bytes = file.content.length / 4 * 3 - (file.content.endsWith("==") ? 2 : file.content.endsWith("=") ? 1 : 0);
48
+ } else return false;
49
+ if (bytes > 2097152) return false;
50
+ total += bytes;
51
+ if (total > 8388608) return false;
52
+ }
53
+ for (const path of paths) if (path.split("/").slice(0, -1).some((_, index, parts) => paths.has(parts.slice(0, index + 1).join("/")))) return false;
54
+ return project.files.some((file) => file.path === project.entryPath && file.encoding === "utf8");
55
+ };
56
+ /** Digest the complete authored graph independently of caller file ordering. */
57
+ const publicTemplateProjectDigest = async (project) => {
58
+ const serialized = JSON.stringify({
59
+ entryPath: project.entryPath,
60
+ files: [...project.files].sort((a, b) => a.path.localeCompare(b.path)).map(({ path, content, encoding }) => ({
61
+ path,
62
+ content,
63
+ encoding
64
+ }))
65
+ });
66
+ const bytes = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(serialized)));
67
+ return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
68
+ };
69
+ const isValidTemplateBrandRecreation = (brandRecreation, project) => brandRecreation !== void 0 && project !== void 0 && brandRecreation.brand.trim().length > 0 && brandRecreation.subject.trim().length > 0;
17
70
  const PUBLIC_TEMPLATE_FONT_TOKENS = /* @__PURE__ */ new Set([
18
71
  "sans",
19
72
  "serif",
@@ -167,37 +220,51 @@ const jsonProjection = (kind, value) => ({
167
220
  contents: `${JSON.stringify(value, null, 2)}\n`
168
221
  });
169
222
  /**
170
- * Emits the five destination projections as deterministic bytes. The importer
223
+ * Emits legacy projections plus the complete project as deterministic bytes. The importer
171
224
  * owns no checked-in destination files; callers choose an explicit output dir.
172
225
  */
173
- const emitTemplateReferencePacket = (packet) => [
174
- {
175
- kind: "source",
176
- relativePath: "preset.tsx",
177
- contents: packet.preset.source
178
- },
179
- jsonProjection("catalog", {
180
- id: packet.preset.id,
181
- channel: packet.preset.channel,
182
- category: packet.preset.category,
183
- name: packet.preset.name,
184
- description: packet.preset.description,
185
- variables: packet.preset.variables
186
- }),
187
- jsonProjection("gallery", {
188
- presetId: packet.preset.id,
189
- ...packet.gallery,
190
- provenance: packet.provenance
191
- }),
192
- jsonProjection("preview", packet.preview),
193
- jsonProjection("editorial", {
194
- cardTitle: packet.publicMetadata.cardTitle,
195
- cardDescription: packet.publicMetadata.cardDescription,
196
- guidance: packet.publicMetadata.guidance,
197
- variables: packet.publicMetadata.variableDescriptions,
198
- seo: packet.publicMetadata.seo
199
- })
200
- ];
226
+ const emitTemplateReferencePacket = (packet) => {
227
+ const project = packet.preset.project;
228
+ if (project !== void 0 && (!isSafePublicTemplateProject(project) || project.files.find((file) => file.path === project.entryPath)?.content !== packet.preset.source)) throw new Error("Invalid public template project");
229
+ if (packet.provenance.source === "brand-recreation" && !isValidTemplateBrandRecreation(packet.provenance.brandRecreation, project)) throw new Error("Invalid public template brand recreation attribution");
230
+ return [
231
+ ...project === void 0 ? [] : [jsonProjection("project", {
232
+ ...project,
233
+ files: [...project.files].sort((a, b) => a.path.localeCompare(b.path))
234
+ }), ...[...project.files].sort((a, b) => a.path.localeCompare(b.path)).map((file) => ({
235
+ kind: "project-file",
236
+ relativePath: `project/${file.path}`,
237
+ contents: file.content,
238
+ encoding: file.encoding
239
+ }))],
240
+ {
241
+ kind: "source",
242
+ relativePath: "preset.tsx",
243
+ contents: packet.preset.source
244
+ },
245
+ jsonProjection("catalog", {
246
+ id: packet.preset.id,
247
+ channel: packet.preset.channel,
248
+ category: packet.preset.category,
249
+ name: packet.preset.name,
250
+ description: packet.preset.description,
251
+ variables: packet.preset.variables
252
+ }),
253
+ jsonProjection("gallery", {
254
+ presetId: packet.preset.id,
255
+ ...packet.gallery,
256
+ provenance: packet.provenance
257
+ }),
258
+ jsonProjection("preview", packet.preview),
259
+ jsonProjection("editorial", {
260
+ cardTitle: packet.publicMetadata.cardTitle,
261
+ cardDescription: packet.publicMetadata.cardDescription,
262
+ guidance: packet.publicMetadata.guidance,
263
+ variables: packet.publicMetadata.variableDescriptions,
264
+ seo: packet.publicMetadata.seo
265
+ })
266
+ ];
267
+ };
201
268
  /**
202
269
  * Validates metadata and TSX syntax, never executing the template. The Vite importer
203
270
  * verifies schema, fixtures and rendered content before writing projections.
@@ -223,20 +290,24 @@ const validatePublicTemplateHandoff = (artifacts) => {
223
290
  if (existingSlugs.has(artifact.gallery.slug) || suppliedSlugs.has(artifact.gallery.slug)) issues.push(issue(id, "duplicate-slug", `canonical slug "${artifact.gallery.slug}" is already present`));
224
291
  suppliedIds.add(id);
225
292
  suppliedSlugs.add(artifact.gallery.slug);
293
+ const project = artifact.preset.project;
294
+ if (project !== void 0 && (!isSafePublicTemplateProject(project) || project.files.find((file) => file.path === project.entryPath)?.content !== artifact.preset.source)) issues.push(issue(id, "source", "project must contain safe bounded unique files and the matching UTF-8 entry source"));
295
+ if (artifact.provenance?.source === "brand-recreation" && !isValidTemplateBrandRecreation(artifact.provenance.brandRecreation, project)) issues.push(issue(id, "provenance", "brand recreations require a complete project, a referenced brand, and its email subject"));
226
296
  if (parsePublicTemplateSource(artifact.preset.source) === void 0) issues.push(issue(id, "source", "source must be a bounded TSX module with a default export; execution is verified by the importer"));
227
297
  if (artifact.preset.channel !== "email") issues.push(issue(id, "channel", "public template source must be an executable email"));
228
298
  if (new Set(artifact.preset.variables).size !== artifact.preset.variables.length || artifact.preset.variables.some((value) => !nonEmpty(value))) issues.push(issue(id, "variables", "declared input fields must be non-empty and unique"));
229
299
  const unsupportedFontTokens = unsupportedPublicTemplateFontTokens(artifact.preset.source);
230
300
  if (unsupportedFontTokens.length > 0) issues.push(issue(id, "font-token", `unsupported public font token: ${unsupportedFontTokens.join(", ")}`));
231
- const sampleVariables = Object.keys(artifact.preview.sampleData);
232
- if (!sameStrings(sampleVariables, artifact.preset.variables)) issues.push(issue(id, "sample-data", "sample data must cover every declared variable exactly"));
233
- if (Object.values(artifact.preview.sampleData).some((value) => !nonEmpty(value))) issues.push(issue(id, "sample-data", "sample data values must be non-empty"));
301
+ const declaredVariables = new Set(artifact.preset.variables);
302
+ const undeclaredSample = Object.keys(artifact.preview.sampleData).filter((variable) => !declaredVariables.has(variable));
303
+ if (undeclaredSample.length > 0) issues.push(issue(id, "sample-data", `sample data supplies undeclared variables: ${sortedUnique(undeclaredSample).join(", ")}`));
304
+ if (Object.values(artifact.preview.sampleData).some((value) => !nonEmptySample(value))) issues.push(issue(id, "sample-data", "sample data values must be non-empty"));
234
305
  const assetVariables = artifact.preview.assets.map((asset) => asset.variable);
235
306
  if (new Set(assetVariables).size !== assetVariables.length) issues.push(issue(id, "assets", "asset variable references must be unique"));
236
307
  for (const asset of artifact.preview.assets) {
237
308
  const value = artifact.preview.sampleData[asset.variable];
238
309
  if (!artifact.preset.variables.includes(asset.variable)) issues.push(issue(id, "assets", `asset "${asset.variable}" is not a declared preset variable`));
239
- if (value === void 0 || !isSafePublicTemplateAsset(value)) issues.push(issue(id, "assets", `asset "${asset.variable}" must reference a bounded HTTPS, /templates/assets, or data:image sample URL`));
310
+ if (typeof value !== "string" || !isSafePublicTemplateAsset(value)) issues.push(issue(id, "assets", `asset "${asset.variable}" must reference a bounded HTTPS, /templates/assets, or data:image sample URL`));
240
311
  }
241
312
  const metadata = artifact.publicMetadata;
242
313
  const metadataStrings = [
@@ -275,6 +346,7 @@ const validatePublicTemplateHandoff = (artifacts) => {
275
346
  variables: artifact.preset.variables
276
347
  },
277
348
  source: artifact.preset.source,
349
+ ...artifact.preset.project === void 0 ? {} : { project: artifact.preset.project },
278
350
  gallery: reference.gallery,
279
351
  preview: artifact.preview,
280
352
  publicMetadata: artifact.publicMetadata,
@@ -283,6 +355,6 @@ const validatePublicTemplateHandoff = (artifacts) => {
283
355
  }));
284
356
  };
285
357
  //#endregion
286
- export { PUBLIC_TEMPLATE_SOURCE_MAX_CHARACTERS, emitTemplateReferencePacket, isSafePublicTemplateAsset, publicTemplateAuthoredStructure, toTemplateReferencePacket, unsupportedPublicTemplateFontTokens, validatePublicTemplateHandoff };
358
+ export { PUBLIC_TEMPLATE_PROJECT_FILE_MAX_BYTES, PUBLIC_TEMPLATE_PROJECT_MAX_BYTES, PUBLIC_TEMPLATE_PROJECT_MAX_FILES, PUBLIC_TEMPLATE_SOURCE_MAX_CHARACTERS, emitTemplateReferencePacket, isSafePublicTemplateAsset, isSafePublicTemplateProject, isSafePublicTemplateProjectPath, isValidTemplateBrandRecreation, publicTemplateAuthoredStructure, publicTemplateProjectDigest, toTemplateReferencePacket, unsupportedPublicTemplateFontTokens, validatePublicTemplateHandoff };
287
359
 
288
360
  //# sourceMappingURL=public-handoff.js.map
@@ -1,4 +1,4 @@
1
- import { EmailPresetId } from "../presets.js";
1
+ import { t as EmailPresetId } from "../catalog-Ck1tAGwO.js";
2
2
  import { PublicTemplate } from "./public-gallery.js";
3
3
  import { PreviewQuality } from "./public-preview.js";
4
4
  import { Result } from "effect";
@@ -1,7 +1,7 @@
1
1
  import { presetCatalog } from "../presets.js";
2
2
  import { registerPublicCorpusEntry } from "./corpus.js";
3
3
  import { publicTemplates } from "./public-gallery.js";
4
- import { presetEmailFixtures, presetModuleSource } from "./sources.js";
4
+ import { presetEmailAssets, presetEmailFixtures, presetModuleSource } from "./sources.js";
5
5
  import { publicTemplatePreviews } from "./public-preview.js";
6
6
  import { Result } from "effect";
7
7
  //#region presets/public-preview-artifacts.ts
@@ -63,14 +63,14 @@ const buildPublicTemplatePreviewArtifact = (template) => {
63
63
  message: "canonical preset source is missing"
64
64
  });
65
65
  const sampleData = fixture.input;
66
- const assets = [];
66
+ const assets = new Set(presetEmailAssets[template.presetId]);
67
67
  for (const asset of preview.assets) {
68
68
  const value = sampleData[asset.variable];
69
- if (value === void 0) return Result.fail({
69
+ if (typeof value !== "string") return Result.fail({
70
70
  presetId: template.presetId,
71
- message: `sample data is missing asset: ${asset.variable}`
71
+ message: `sample data is missing a string asset: ${asset.variable}`
72
72
  });
73
- assets.push(value);
73
+ assets.add(value);
74
74
  }
75
75
  return Result.succeed({
76
76
  presetId: template.presetId,
@@ -80,7 +80,7 @@ const buildPublicTemplatePreviewArtifact = (template) => {
80
80
  quality: preview.quality,
81
81
  source,
82
82
  html: fixture.html,
83
- assets,
83
+ assets: [...assets],
84
84
  renders: renderInputs(template.slug, fixture.html)
85
85
  });
86
86
  };
@@ -1,10 +1,14 @@
1
1
  //#region presets/public-preview.d.ts
2
2
  type PreviewQuality = "ready" | "asset-free";
3
+ /** A declared fixture value: JSON, so a template can take a list of stories as well as a string. */
4
+ type PreviewSampleValue = string | number | boolean | null | ReadonlyArray<PreviewSampleValue> | {
5
+ readonly [key: string]: PreviewSampleValue;
6
+ };
3
7
  interface PublicTemplatePreview {
4
8
  readonly subject: string;
5
9
  readonly preheader: string;
6
10
  readonly quality: PreviewQuality;
7
- readonly sampleData: Readonly<Record<string, string>>;
11
+ readonly sampleData: Readonly<Record<string, PreviewSampleValue>>;
8
12
  readonly assets: ReadonlyArray<{
9
13
  readonly variable: string;
10
14
  readonly kind: "image" | "logo";
@@ -12,19 +16,21 @@ interface PublicTemplatePreview {
12
16
  }
13
17
  /** Gallery metadata augments the actual default fixture; it does not supply render input. */
14
18
  declare const publicTemplatePreviews: {
19
+ readonly "linear-login-code": PublicTemplatePreview;
20
+ readonly "product-newsletter": PublicTemplatePreview;
21
+ readonly "order-receipt": PublicTemplatePreview;
22
+ readonly "vercel-invitation": PublicTemplatePreview;
23
+ readonly "product-launch-promo": PublicTemplatePreview;
15
24
  readonly welcome: PublicTemplatePreview;
16
25
  readonly "email-verification": PublicTemplatePreview;
17
26
  readonly otp: PublicTemplatePreview;
18
27
  readonly "password-reset": PublicTemplatePreview;
19
- readonly receipt: PublicTemplatePreview;
20
28
  readonly "payment-failed": PublicTemplatePreview;
21
29
  readonly "shipping-update": PublicTemplatePreview;
22
30
  readonly notification: PublicTemplatePreview;
23
31
  readonly "team-invite": PublicTemplatePreview;
24
32
  readonly "product-digest": PublicTemplatePreview;
25
- readonly newsletter: PublicTemplatePreview;
26
33
  readonly announcement: PublicTemplatePreview;
27
- readonly promo: PublicTemplatePreview;
28
34
  readonly "event-invite": PublicTemplatePreview;
29
35
  readonly "membership-promo": PublicTemplatePreview;
30
36
  readonly "onboarding-step": PublicTemplatePreview;
@@ -36,7 +42,6 @@ declare const publicTemplatePreviews: {
36
42
  readonly "catalog-sale-newsletter": PublicTemplatePreview;
37
43
  readonly "limited-time-savings": PublicTemplatePreview;
38
44
  readonly "rewards-milestone": PublicTemplatePreview;
39
- readonly "order-delivered": PublicTemplatePreview;
40
45
  readonly "travel-rewards-promo": PublicTemplatePreview;
41
46
  readonly "events-roundup": PublicTemplatePreview;
42
47
  readonly "product-onboarding-tour": PublicTemplatePreview;
@@ -52,5 +57,5 @@ declare const publicTemplatePreviews: {
52
57
  readonly "season-clearance-promo": PublicTemplatePreview;
53
58
  };
54
59
  //#endregion
55
- export { PreviewQuality, PublicTemplatePreview, publicTemplatePreviews };
60
+ export { PreviewQuality, PreviewSampleValue, PublicTemplatePreview, publicTemplatePreviews };
56
61
  //# sourceMappingURL=public-preview.d.ts.map