@rebuy/rebuy 3.26.0 → 3.28.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 (51) hide show
  1. package/dist/index.cjs +902 -750
  2. package/dist/index.mjs +901 -749
  3. package/dist/schema/checkout-and-beyond/constants.cjs +5 -0
  4. package/dist/schema/checkout-and-beyond/constants.mjs +5 -0
  5. package/dist/schema/checkout-and-beyond/index.cjs +97 -68
  6. package/dist/schema/checkout-and-beyond/index.mjs +97 -68
  7. package/dist/schema/index.d.ts +6 -0
  8. package/dist/schema/postPurchaseEligibility.d.ts +2 -2
  9. package/dist/schema/postPurchaseExitPolicy.d.ts +20 -0
  10. package/dist/schema/postPurchaseIdentity.d.ts +9 -0
  11. package/dist/schema/postPurchaseOrderDecision.d.ts +10 -0
  12. package/dist/schema/postPurchasePolicy.d.ts +62 -0
  13. package/dist/schema/postPurchaseSelection.d.ts +29 -0
  14. package/dist/schema/postPurchaseSession.d.ts +112 -0
  15. package/dist/schema/postPurchaseSessionClose.d.ts +25 -0
  16. package/dist/schema/postPurchaseShadow.d.ts +56 -1
  17. package/dist/schema/postPurchaseSkipTrace.d.ts +2 -2
  18. package/dist/schema/widget-data.cjs +160 -135
  19. package/dist/schema/widget-data.mjs +160 -135
  20. package/dist/schema/widgetData.d.ts +24 -0
  21. package/dist/schema/widgets/checkout-and-beyond/banner.d.ts +8 -0
  22. package/dist/schema/widgets/checkout-and-beyond/carousel.d.ts +8 -0
  23. package/dist/schema/widgets/checkout-and-beyond/cartLine.d.ts +8 -0
  24. package/dist/schema/widgets/checkout-and-beyond/common.d.ts +13 -1
  25. package/dist/schema/widgets/checkout-and-beyond/index.d.ts +1 -0
  26. package/dist/schema/widgets/checkout-and-beyond/layout.d.ts +17 -1
  27. package/dist/schema/widgets/checkout-and-beyond/offers.d.ts +8 -0
  28. package/dist/schema/widgets/checkout-and-beyond/progressBar.d.ts +8 -0
  29. package/dist/schema/widgets/checkout-and-beyond/reviews.d.ts +2 -0
  30. package/dist/schema/widgets/checkout-and-beyond/root.d.ts +8 -0
  31. package/dist/schema/widgets/checkout-and-beyond/separator.d.ts +192 -0
  32. package/dist/schema/widgets/checkout-and-beyond/shared.d.ts +2 -1
  33. package/dist/schema/widgets/contentBlock.d.ts +8 -0
  34. package/dist/schema/widgets/lineItemEditor.d.ts +8 -0
  35. package/dist/schema/widgets/post-purchase-offer/constants.d.ts +2 -2
  36. package/dist/schema/widgets/rebuyButton.d.ts +8 -0
  37. package/dist/server/index.cjs +601 -188
  38. package/dist/server/index.mjs +601 -188
  39. package/dist/server/requestSchemas.d.ts +1 -1
  40. package/dist/transforms/index.cjs +481 -59
  41. package/dist/transforms/index.d.ts +2 -0
  42. package/dist/transforms/index.mjs +481 -59
  43. package/dist/transforms/postPurchase/convertCalloutBlock.d.ts +8 -0
  44. package/dist/transforms/postPurchase/convertMessagePreview.d.ts +8 -0
  45. package/dist/transforms/postPurchase/convertPayButtonBlock.d.ts +4 -0
  46. package/dist/transforms/postPurchase/convertSeparatorBlock.d.ts +4 -0
  47. package/dist/transforms/postPurchase/convertTextBlock.d.ts +4 -0
  48. package/dist/transforms/postPurchase/convertTimerBlock.d.ts +4 -0
  49. package/dist/transforms/postPurchase/styledTextRun.d.ts +3 -0
  50. package/dist/transforms/postPurchase/types.d.ts +8 -0
  51. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  // src/schema/widgets/checkout-and-beyond/image.ts
2
- import { v7 as uuidv712 } from "uuid";
3
- import { z as z20 } from "zod";
2
+ import { v7 as uuidv713 } from "uuid";
3
+ import { z as z21 } from "zod";
4
4
 
5
5
  // src/schema/widgets/checkout-and-beyond/common.ts
6
6
  var freezeEnum = (values) => Object.freeze(Object.fromEntries(values.map((v) => [v, v])));
@@ -109,6 +109,8 @@ var languageKeys = [
109
109
  "zh"
110
110
  ];
111
111
  var LanguageKey = freezeEnum(languageKeys);
112
+ var layoutFrames = ["callout", "offer-content"];
113
+ var LayoutFrame = freezeEnum(layoutFrames);
112
114
  var mutatorEvents = ["item_added", "quantity_changed", "variant_selected"];
113
115
  var MutatorEvent = freezeEnum(mutatorEvents);
114
116
  var objectFits = ["cover", "contain"];
@@ -147,6 +149,7 @@ var sectionTypes = [
147
149
  "progressBar",
148
150
  "quantity",
149
151
  "reviews",
152
+ "separator",
150
153
  "text",
151
154
  "variants"
152
155
  ];
@@ -290,7 +293,7 @@ var ROOT_RELATIVE_PATH_REGEX = /^\/(?!\/)/;
290
293
  var HTML_TAGS_REGEX = /<\/?[a-zA-Z][^>]*>/g;
291
294
 
292
295
  // src/schema/widgets/checkout-and-beyond/shared.ts
293
- import { z as z19 } from "zod";
296
+ import { z as z20 } from "zod";
294
297
 
295
298
  // src/schema/widgets/checkout-and-beyond/banner.ts
296
299
  import { z as z4 } from "zod";
@@ -445,6 +448,10 @@ var CABVariableFields = {
445
448
 
446
449
  // src/schema/widgets/checkout-and-beyond/layout.ts
447
450
  var GridItem = z3.union([z3.literal("auto"), z3.literal("fill"), z3.string().regex(/^\d+%$/), z3.number()]);
451
+ var CABLayoutWrapping = z3.object({
452
+ breakAt: z3.number().positive(),
453
+ maxPerLine: z3.number().int().positive()
454
+ });
448
455
  var CABLayoutSection = z3.object({
449
456
  ...CABVariableFields,
450
457
  alignment: z3.object({
@@ -457,6 +464,11 @@ var CABLayoutSection = z3.object({
457
464
  border: z3.lazy(() => CABBorder),
458
465
  buttonField: z3.enum(buttonFields).optional(),
459
466
  direction: z3.enum(directions).default(Direction.rows),
467
+ /**
468
+ * Platform chrome around the section, not a layout behavior: `callout` is a subdued box with block borders
469
+ * (the legacy post-purchase callout banner), `offer-content` the post-purchase offer's own content card.
470
+ */
471
+ frame: z3.enum(layoutFrames).optional(),
460
472
  grid: z3.object({
461
473
  columns: z3.union([z3.array(GridItem), z3.undefined()]).default(() => ["auto"]),
462
474
  rows: z3.union([z3.array(GridItem), z3.undefined()]).default(() => ["auto"])
@@ -469,7 +481,8 @@ var CABLayoutSection = z3.object({
469
481
  spacing: z3.enum(spacings).default(Spacing.base),
470
482
  /** Fire-and-forget impression pixel POSTed once when the section is shown (e.g. a Monetize offer view). */
471
483
  viewUrl: z3.string().optional(),
472
- width: z3.number().default(100)
484
+ width: z3.number().default(100),
485
+ wrapping: CABLayoutWrapping.optional()
473
486
  });
474
487
 
475
488
  // src/schema/widgets/checkout-and-beyond/utils.ts
@@ -1333,35 +1346,46 @@ var CABReviewsSection = z17.object({
1333
1346
  name: z17.string().optional(),
1334
1347
  sectionId: z17.uuid().default(() => uuidv710()),
1335
1348
  sectionType: z17.literal(SectionType.reviews).default(SectionType.reviews),
1336
- size: z17.enum(reviewsSizes).default(ReviewsSize.default)
1349
+ size: z17.enum(reviewsSizes).default(ReviewsSize.default),
1350
+ strokeColor: z17.string().default("#fadb14"),
1351
+ strokeWidth: z17.number().nonnegative().default(0)
1337
1352
  });
1338
1353
 
1339
- // src/schema/widgets/checkout-and-beyond/variants.ts
1340
- import { slice } from "es-toolkit/compat";
1354
+ // src/schema/widgets/checkout-and-beyond/separator.ts
1341
1355
  import { v7 as uuidv711 } from "uuid";
1342
1356
  import { z as z18 } from "zod";
1343
- var CABVariantsSection = z18.object({
1357
+ var CABSeparatorSection = z18.object({
1344
1358
  ...CABVariableFields,
1345
- hideOutOfStockVariants: z18.boolean().default(false),
1346
- name: z18.string().optional(),
1347
1359
  sectionId: z18.uuid().default(() => uuidv711()),
1348
- sectionType: z18.literal(SectionType.variants).default(SectionType.variants),
1349
- selector: z18.enum(slice(variantSelectors, 0, 3)).default(VariantSelector.menu),
1350
- variantMode: z18.enum(variantModes).default(VariantMode.multiple)
1360
+ sectionType: z18.literal(SectionType.separator).default(SectionType.separator)
1361
+ });
1362
+
1363
+ // src/schema/widgets/checkout-and-beyond/variants.ts
1364
+ import { slice } from "es-toolkit/compat";
1365
+ import { v7 as uuidv712 } from "uuid";
1366
+ import { z as z19 } from "zod";
1367
+ var CABVariantsSection = z19.object({
1368
+ ...CABVariableFields,
1369
+ hideOutOfStockVariants: z19.boolean().default(false),
1370
+ name: z19.string().optional(),
1371
+ sectionId: z19.uuid().default(() => uuidv712()),
1372
+ sectionType: z19.literal(SectionType.variants).default(SectionType.variants),
1373
+ selector: z19.enum(slice(variantSelectors, 0, 3)).default(VariantSelector.menu),
1374
+ variantMode: z19.enum(variantModes).default(VariantMode.multiple)
1351
1375
  });
1352
1376
 
1353
1377
  // src/schema/widgets/checkout-and-beyond/shared.ts
1354
- var CABBorder = z19.object({
1355
- radius: z19.enum(borderRadii).default(BorderRadius.base),
1356
- style: z19.enum(borderStyles).default(BorderStyle.none),
1357
- width: z19.enum(borderWidths).default(BorderWidth.base)
1378
+ var CABBorder = z20.object({
1379
+ radius: z20.enum(borderRadii).default(BorderRadius.base),
1380
+ style: z20.enum(borderStyles).default(BorderStyle.none),
1381
+ width: z20.enum(borderWidths).default(BorderWidth.base)
1358
1382
  }).default({
1359
1383
  radius: BorderRadius.base,
1360
1384
  style: BorderStyle.none,
1361
1385
  width: BorderWidth.base
1362
1386
  });
1363
- var CABSection = z19.lazy(
1364
- () => z19.discriminatedUnion("sectionType", [
1387
+ var CABSection = z20.lazy(
1388
+ () => z20.discriminatedUnion("sectionType", [
1365
1389
  CABBannerSection,
1366
1390
  CABButtonSection,
1367
1391
  CABCarouselSection,
@@ -1377,23 +1401,24 @@ var CABSection = z19.lazy(
1377
1401
  CABProgressBarSection,
1378
1402
  CABQuantitySection,
1379
1403
  CABReviewsSection,
1404
+ CABSeparatorSection,
1380
1405
  CABTextSection,
1381
1406
  CABVariantsSection
1382
1407
  ])
1383
1408
  );
1384
1409
 
1385
1410
  // src/schema/widgets/checkout-and-beyond/image.ts
1386
- var CABImageSectionFields = z20.object({
1411
+ var CABImageSectionFields = z21.object({
1387
1412
  ...CABVariableFields,
1388
- altText: z20.string().refine(checkForHTML, NO_HTML).default(""),
1413
+ altText: z21.string().refine(checkForHTML, NO_HTML).default(""),
1389
1414
  /**
1390
1415
  * Image width÷height (e.g. `46` for the progress-bar fill); `null` renders at natural size. Any POSITIVE
1391
1416
  * ratio — never limited to 1, but never `0`/negative either: a renderer dividing by it would get `Infinity`,
1392
1417
  * and CSS `aspect-ratio` drops a negative value and silently reverts to natural size.
1393
1418
  */
1394
- aspectRatio: z20.number().positive().nullable().default(null),
1395
- border: z20.lazy(() => CABBorder),
1396
- buttonField: z20.enum(buttonFields).optional(),
1419
+ aspectRatio: z21.number().positive().nullable().default(null),
1420
+ border: z21.lazy(() => CABBorder),
1421
+ buttonField: z21.enum(buttonFields).optional(),
1397
1422
  /**
1398
1423
  * `icon` renders `source` as a single `s-icon` by name (the uber-image path covers icons too), reading
1399
1424
  * `iconSize`/`iconTone`. The other values are a harmless informational holdover from the previous
@@ -1412,29 +1437,29 @@ var CABImageSectionFields = z20.object({
1412
1437
  * behavior degraded gracefully and told us about it. The client-assembled half of the invariant was never
1413
1438
  * the risky half.
1414
1439
  */
1415
- category: z20.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
1440
+ category: z21.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
1416
1441
  /** `icon`-mode only: the `s-icon` `size`; `null` ⇒ the component default (`base`). Ignored by image treatments. */
1417
- iconSize: z20.enum(iconSizes).nullable().default(null),
1442
+ iconSize: z21.enum(iconSizes).nullable().default(null),
1418
1443
  /** `icon`-mode only: the `s-icon` `tone`; `null` ⇒ the component default (`auto`). Ignored by image treatments. */
1419
- iconTone: z20.enum(iconTones).nullable().default(null),
1420
- name: z20.string().optional(),
1421
- naturalHeight: z20.number().default(0),
1422
- naturalWidth: z20.number().default(0),
1444
+ iconTone: z21.enum(iconTones).nullable().default(null),
1445
+ name: z21.string().optional(),
1446
+ naturalHeight: z21.number().default(0),
1447
+ naturalWidth: z21.number().default(0),
1423
1448
  /**
1424
1449
  * `contain` (the component default): dimensionless images render in s-image's 1/1 default frame, and
1425
1450
  * `cover` would crop non-square art (payment badges lost their edges — 15993); `contain` letterboxes.
1426
1451
  */
1427
- objectFit: z20.enum(objectFits).default(ObjectFit.contain),
1428
- sectionId: z20.uuid().default(() => uuidv712()),
1429
- sectionType: z20.literal(SectionType.image).default(SectionType.image),
1452
+ objectFit: z21.enum(objectFits).default(ObjectFit.contain),
1453
+ sectionId: z21.uuid().default(() => uuidv713()),
1454
+ sectionType: z21.literal(SectionType.image).default(SectionType.image),
1430
1455
  /**
1431
1456
  * An image URL or dynamic token, an empty default, or — when `category: 'icon'` — an icon NAME. Icon mode
1432
1457
  * takes a name or `''` only, NOT a token: no renderer resolves a token to an icon today, so accepting one
1433
1458
  * would promise a capability that doesn't exist. Widen the refine's carve-out to `DYNAMIC_TOKEN_REGEX` when a
1434
1459
  * server-chosen tier icon actually needs it.
1435
1460
  */
1436
- source: z20.union([z20.url(), z20.literal(""), z20.string().regex(DYNAMIC_TOKEN_REGEX), z20.enum(iconNames)]).default(""),
1437
- width: z20.number().default(100)
1461
+ source: z21.union([z21.url(), z21.literal(""), z21.string().regex(DYNAMIC_TOKEN_REGEX), z21.enum(iconNames)]).default(""),
1462
+ width: z21.number().default(100)
1438
1463
  });
1439
1464
  var iconNameSet = new Set(iconNames);
1440
1465
  var isIconName = (source) => iconNameSet.has(source);
@@ -1585,7 +1610,7 @@ var convertContentBlockTextToV2 = (language, text = literalText, textAlign = "ce
1585
1610
  };
1586
1611
 
1587
1612
  // src/schema/widgets/checkout-and-beyond/root.ts
1588
- import { z as z21 } from "zod";
1613
+ import { z as z22 } from "zod";
1589
1614
 
1590
1615
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
1591
1616
  var UI_LABELS = {
@@ -1605,8 +1630,8 @@ var UI_LABELS = {
1605
1630
  };
1606
1631
 
1607
1632
  // src/schema/widgets/checkout-and-beyond/root.ts
1608
- var localized = (fallback) => z21.record(z21.string(), z21.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1609
- var CABUILabels = z21.object({
1633
+ var localized = (fallback) => z22.record(z22.string(), z22.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1634
+ var CABUILabels = z22.object({
1610
1635
  currentPage: localized(UI_LABELS.currentPage),
1611
1636
  guest: localized(UI_LABELS.guest),
1612
1637
  loadingOptions: localized(UI_LABELS.loadingOptions),
@@ -1631,37 +1656,37 @@ var CABUILabels = z21.object({
1631
1656
  subscriptionOptions: { ...UI_LABELS.subscriptionOptions },
1632
1657
  updating: { ...UI_LABELS.updating }
1633
1658
  }));
1634
- var TargetArea = z21.object({
1635
- fill: z21.boolean().optional(),
1636
- flip: z21.enum(["both", "horizontal", "vertical"]).optional(),
1637
- icon: z21.string(),
1638
- label: z21.string(),
1639
- width: z21.string()
1659
+ var TargetArea = z22.object({
1660
+ fill: z22.boolean().optional(),
1661
+ flip: z22.enum(["both", "horizontal", "vertical"]).optional(),
1662
+ icon: z22.string(),
1663
+ label: z22.string(),
1664
+ width: z22.string()
1640
1665
  }).default(targetAreas[EditorMode.checkoutExtension][1]);
1641
- var CABTracking = z21.object({
1642
- enableAttribution: z21.boolean().nullish().transform((value) => value ?? true),
1643
- enableSource: z21.boolean().nullish().transform((value) => value ?? true),
1644
- enableWidget: z21.boolean().nullish().transform((value) => value ?? true)
1666
+ var CABTracking = z22.object({
1667
+ enableAttribution: z22.boolean().nullish().transform((value) => value ?? true),
1668
+ enableSource: z22.boolean().nullish().transform((value) => value ?? true),
1669
+ enableWidget: z22.boolean().nullish().transform((value) => value ?? true)
1645
1670
  }).nullish().transform((value) => value ?? { enableAttribution: true, enableSource: true, enableWidget: true });
1646
- var CABExperiment = z21.object({
1647
- elementId: z21.number(),
1648
- experimentId: z21.number(),
1649
- experimentType: z21.string(),
1650
- selectedId: z21.number()
1671
+ var CABExperiment = z22.object({
1672
+ elementId: z22.number(),
1673
+ experimentId: z22.number(),
1674
+ experimentType: z22.string(),
1675
+ selectedId: z22.number()
1651
1676
  });
1652
1677
  var CABRootSection = CABLayoutSection.extend({
1653
- editorMode: z21.enum(editorModes).default(EditorMode.checkoutExtension),
1678
+ editorMode: z22.enum(editorModes).default(EditorMode.checkoutExtension),
1654
1679
  experiment: CABExperiment.optional(),
1655
1680
  // Same rule as CABTracking above: the v1 converters pass raw legacy `previewMode` through, so a
1656
1681
  // `null` must fall back rather than throw the widget; malformed values still throw.
1657
- previewMode: z21.boolean().nullish().transform((value) => value ?? false),
1658
- storeId: z21.number().nullable().default(null),
1682
+ previewMode: z22.boolean().nullish().transform((value) => value ?? false),
1683
+ storeId: z22.number().nullable().default(null),
1659
1684
  targetArea: TargetArea.nullable(),
1660
1685
  tracking: CABTracking,
1661
- type: z21.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
1686
+ type: z22.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
1662
1687
  uiLabels: CABUILabels,
1663
- version: z21.literal(2).default(2),
1664
- widgetId: z21.number().nullable().default(null)
1688
+ version: z22.literal(2).default(2),
1689
+ widgetId: z22.number().nullable().default(null)
1665
1690
  });
1666
1691
 
1667
1692
  // src/transforms/v1Location.ts
@@ -3501,6 +3526,401 @@ var convertOfferToV2 = ({ id, name, settings }) => {
3501
3526
  // src/transforms/parseShielded.ts
3502
3527
  var parseShielded = (schema, raw, transform = (input) => input) => schema.parse(transform(convertNumericObjects(deepCamelCase(raw))));
3503
3528
 
3529
+ // src/transforms/postPurchase/convertMessagePreview.ts
3530
+ import { z as z27 } from "zod";
3531
+
3532
+ // src/server/shared.ts
3533
+ var NotFoundError = class extends Error {
3534
+ constructor(message) {
3535
+ super(message);
3536
+ this.name = "NotFoundError";
3537
+ }
3538
+ };
3539
+
3540
+ // src/transforms/postPurchase/convertCalloutBlock.ts
3541
+ import { z as z25 } from "zod";
3542
+
3543
+ // src/schema/widgets/post-purchase-offer/postPurchaseBlocks.ts
3544
+ import { get as get2, isEqual } from "es-toolkit/compat";
3545
+ import { v4 as uuidv4 } from "uuid";
3546
+ import { z as z24 } from "zod";
3547
+
3548
+ // src/schema/widgets/post-purchase-offer/constants.ts
3549
+ import { z as z23 } from "zod";
3550
+ var blockTypes = [
3551
+ "callout_banner",
3552
+ "image",
3553
+ "image_content",
3554
+ "pay_button",
3555
+ "product_information",
3556
+ "separator",
3557
+ "text",
3558
+ "timer"
3559
+ ];
3560
+ var blockType = z23.enum(blockTypes);
3561
+ var BlockType = blockType.enum;
3562
+
3563
+ // src/schema/widgets/post-purchase-offer/postPurchaseBlocks.ts
3564
+ var TextAlignment2 = z24.union([z24.enum(["leading", "center", "trailing"]), z24.unknown().transform(() => "leading")]);
3565
+ var TextSize = z24.union([
3566
+ z24.enum(["xsmall", "small", "base", "default", "medium", "large", "xlarge"]),
3567
+ z24.unknown().transform(() => "medium")
3568
+ ]);
3569
+ var CalloutBannerBlock = z24.object({
3570
+ id: z24.string().optional().default(() => uuidv4()),
3571
+ name: z24.string().optional(),
3572
+ settings: z24.object({
3573
+ superTitle: z24.union([z24.string(), TiptapDocument]).default(() => "Limited-time Offer"),
3574
+ title: z24.union([z24.string(), TiptapDocument]).default(() => "Add this customer favorite to your order")
3575
+ }),
3576
+ styles: z24.object({
3577
+ superTitleEmphasized: z24.boolean().default(false),
3578
+ superTitleSize: TextSize.default("large"),
3579
+ textAlignment: TextAlignment2.default("center"),
3580
+ titleEmphasized: z24.boolean().default(true),
3581
+ titleSize: TextSize.default("large")
3582
+ }),
3583
+ type: z24.literal(BlockType.callout_banner).default(BlockType.callout_banner)
3584
+ });
3585
+ var ImageBlock = z24.object({
3586
+ id: z24.string().optional().default(() => uuidv4()),
3587
+ name: z24.string().optional(),
3588
+ settings: z24.union([
3589
+ z24.object({
3590
+ /** This isn't used in the post-purchase offer widget */
3591
+ alt: z24.string().optional().default(""),
3592
+ image: z24.union([z24.literal(""), z24.url()]).default(""),
3593
+ imageSize: z24.number().default(20),
3594
+ imageType: z24.enum(["URL", "UPLOAD"]).default("URL")
3595
+ }),
3596
+ z24.array(z24.never()).transform(() => ({}))
3597
+ ]),
3598
+ type: z24.literal(BlockType.image).default(BlockType.image)
3599
+ });
3600
+ var ImageContentBlock = z24.object({
3601
+ id: z24.string().optional().default(() => uuidv4()),
3602
+ name: z24.string().optional(),
3603
+ settings: z24.object({
3604
+ alt: z24.string().optional().default(""),
3605
+ description: z24.union([z24.string(), TiptapDocument, z24.null()]).default(
3606
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
3607
+ ),
3608
+ descriptionSize: TextSize.default("medium"),
3609
+ horizontalAlignment: TextAlignment2.default("leading"),
3610
+ image: z24.union([z24.literal(""), z24.url()]).default(""),
3611
+ imagePlacement: z24.enum(["bottom", "left", "right", "top"]).optional().default("left"),
3612
+ imageSize: z24.number().default(20),
3613
+ superTitle: z24.union([z24.string(), TiptapDocument]).default("Lorem Ipsum!"),
3614
+ superTitleSize: TextSize.default("medium"),
3615
+ /** This isn't configurable in the admin-nextjs editor */
3616
+ swapContent: z24.boolean().optional().default(false),
3617
+ title: z24.union([z24.string(), TiptapDocument]).nullable().default("Lorem ipsum dolor sit amet"),
3618
+ titleSize: TextSize.default("medium")
3619
+ }),
3620
+ type: z24.literal(BlockType.image_content).default(BlockType.image_content)
3621
+ });
3622
+ var PayButtonBlock = z24.object({
3623
+ id: z24.string().optional().default(() => uuidv4()),
3624
+ name: z24.string().optional(),
3625
+ settings: z24.union([
3626
+ z24.object({
3627
+ label: z24.string().default("Pay Now")
3628
+ }),
3629
+ z24.array(z24.never()).transform(() => ({
3630
+ label: "Pay Now"
3631
+ }))
3632
+ ]),
3633
+ styles: z24.union([
3634
+ z24.object({
3635
+ buttonWidth: z24.number().min(10).max(100).default(50)
3636
+ }),
3637
+ z24.array(z24.never()).transform(() => ({
3638
+ buttonWidth: 50
3639
+ }))
3640
+ ]),
3641
+ type: z24.literal(BlockType.pay_button).default(BlockType.pay_button)
3642
+ });
3643
+ var ProductInformationBlock = z24.object({
3644
+ /** This isn't configurable in the admin-nextjs editor */
3645
+ hideProductImage: z24.boolean().optional().default(false),
3646
+ id: z24.string().optional().default(() => uuidv4()),
3647
+ name: z24.string().optional(),
3648
+ type: z24.literal(BlockType.product_information).default(BlockType.product_information)
3649
+ });
3650
+ var SeparatorBlock = z24.object({
3651
+ id: z24.string().optional().default(() => uuidv4()),
3652
+ name: z24.string().optional(),
3653
+ type: z24.literal(BlockType.separator).default(BlockType.separator)
3654
+ });
3655
+ var TextBlock = z24.object({
3656
+ id: z24.string().optional().default(() => uuidv4()),
3657
+ name: z24.string().optional(),
3658
+ settings: z24.object({
3659
+ description: z24.union([z24.string(), TiptapDocument]).optional().default(
3660
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
3661
+ ),
3662
+ /** This isn't used in the post-purchase offer widget */
3663
+ descriptionSize: TextSize.default("medium"),
3664
+ horizontalAlignment: TextAlignment2.default("leading"),
3665
+ superTitle: z24.union([z24.string(), TiptapDocument]).default("Super Title"),
3666
+ /** This isn't used in the post-purchase offer widget */
3667
+ superTitleSize: TextSize.default("medium"),
3668
+ title: z24.union([z24.string(), TiptapDocument]).nullable().default("Lorem ipsum dolor sit amet."),
3669
+ /** This isn't used in the post-purchase offer widget */
3670
+ titleSize: TextSize.default("medium")
3671
+ }),
3672
+ type: z24.literal(BlockType.text).default(BlockType.text)
3673
+ });
3674
+ var TimerBlock = z24.object({
3675
+ id: z24.string().optional().default(() => uuidv4()),
3676
+ name: z24.string().optional(),
3677
+ settings: z24.object({
3678
+ durationMinutes: z24.number().min(0).default(10),
3679
+ durationSeconds: z24.union([z24.number().min(0), z24.unknown().transform(() => 0)]).default(0),
3680
+ endOffer: z24.boolean().default(true),
3681
+ title: z24.union([z24.string(), TiptapDocument]).default("Hurry \u2014 your special offer ends in:")
3682
+ }),
3683
+ styles: z24.object({
3684
+ textAlignment: TextAlignment2.default("center"),
3685
+ timerBackgroundColor: z24.enum(["info", "warning", "success", "critical"]).default("warning"),
3686
+ timerEmphasized: z24.union([z24.boolean(), z24.unknown().transform(() => true)]).default(true),
3687
+ timerSize: TextSize.default("medium"),
3688
+ timerWidth: z24.number().min(10).max(100).optional().default(100),
3689
+ titleEmphasized: z24.union([z24.boolean(), z24.unknown().transform(() => true)]).default(false),
3690
+ titleSize: TextSize.default("medium")
3691
+ }),
3692
+ type: z24.literal(BlockType.timer).default(BlockType.timer)
3693
+ });
3694
+ var PostPurchaseBlock = z24.discriminatedUnion("type", [
3695
+ CalloutBannerBlock,
3696
+ ImageBlock,
3697
+ ImageContentBlock,
3698
+ PayButtonBlock,
3699
+ ProductInformationBlock,
3700
+ SeparatorBlock,
3701
+ TextBlock,
3702
+ TimerBlock
3703
+ ]);
3704
+
3705
+ // src/transforms/postPurchase/styledTextRun.ts
3706
+ var sizes = {
3707
+ base: "base",
3708
+ default: "base",
3709
+ large: "large",
3710
+ medium: "medium",
3711
+ small: "small",
3712
+ xlarge: "extraLarge",
3713
+ xsmall: "extraSmall"
3714
+ };
3715
+ var styledTextRun = (text, emphasized, size) => ({
3716
+ marks: [
3717
+ ...emphasized ? [{ type: "bold" }] : [],
3718
+ { attrs: { color: "base", fontSize: sizes[size] }, type: "textStyle" }
3719
+ ],
3720
+ text,
3721
+ type: "text"
3722
+ });
3723
+
3724
+ // src/transforms/postPurchase/convertCalloutBlock.ts
3725
+ var fields = ["superTitle", "title"];
3726
+ var Shell = CalloutBannerBlock.pick({ styles: true }).extend({
3727
+ settings: z25.object({ superTitle: z25.unknown().optional(), title: z25.unknown().optional() })
3728
+ });
3729
+ var convertCalloutBlock = (raw, report) => {
3730
+ const omit = (detail) => {
3731
+ report?.({ detail, kind: "section" });
3732
+ return [];
3733
+ };
3734
+ const shell = Shell.safeParse(raw);
3735
+ if (!shell.success) return omit("Unreadable post-purchase callout");
3736
+ const values = fields.map((field) => ({
3737
+ field,
3738
+ result: CalloutBannerBlock.shape.settings.shape[field].safeParse(shell.data.settings[field])
3739
+ }));
3740
+ const styled = values.every(({ result }) => result.success && typeof result.data === "string");
3741
+ const styles2 = shell.data.styles;
3742
+ const horizontal = styled ? { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment] : "center";
3743
+ const sections = values.flatMap(({ field, result }) => {
3744
+ if (!result.success) return omit(`Unreadable post-purchase callout field: ${field}`);
3745
+ const text = result.data;
3746
+ if (text === "") return [];
3747
+ const content = styled && typeof text === "string" ? {
3748
+ content: [
3749
+ {
3750
+ attrs: { textAlign: horizontal },
3751
+ content: [styledTextRun(text, styles2[`${field}Emphasized`], styles2[`${field}Size`])]
3752
+ }
3753
+ ]
3754
+ } : text;
3755
+ const section = CABTextSection.safeParse({ content: { en: content } });
3756
+ return section.success ? [section.data] : omit(`Unreadable post-purchase callout field: ${field}`);
3757
+ });
3758
+ return sections.length ? [CABLayoutSection.parse({ alignment: { horizontal }, frame: "callout", sections })] : [];
3759
+ };
3760
+
3761
+ // src/transforms/postPurchase/convertPayButtonBlock.ts
3762
+ var convertPayButtonBlock = (raw, report) => {
3763
+ const omit = () => {
3764
+ report?.({ detail: "Unreadable post-purchase Pay block", kind: "section" });
3765
+ return [];
3766
+ };
3767
+ const parsed = PayButtonBlock.safeParse(raw);
3768
+ if (!parsed.success) return omit();
3769
+ const { settings, styles: styles2 } = parsed.data;
3770
+ const label = settings.label ? `${settings.label} \xB7 {{total}}` : "{{total}}";
3771
+ const text = CABTextSection.safeParse({ content: { en: label } });
3772
+ if (!text.success) return omit();
3773
+ return [
3774
+ CABLayoutSection.parse({
3775
+ alignment: { horizontal: "center" },
3776
+ direction: "grid",
3777
+ grid: { columns: ["100%"] },
3778
+ sections: [
3779
+ CABButtonSection.parse({
3780
+ action: "addToOrder",
3781
+ sections: [text.data]
3782
+ })
3783
+ ],
3784
+ width: styles2.buttonWidth
3785
+ })
3786
+ ];
3787
+ };
3788
+
3789
+ // src/transforms/postPurchase/convertSeparatorBlock.ts
3790
+ var convertSeparatorBlock = (raw, report) => {
3791
+ if (!SeparatorBlock.safeParse(raw).success) {
3792
+ report?.({ detail: "Unreadable post-purchase separator", kind: "section" });
3793
+ return [];
3794
+ }
3795
+ return [CABSeparatorSection.parse({})];
3796
+ };
3797
+
3798
+ // src/transforms/postPurchase/convertTextBlock.ts
3799
+ import { z as z26 } from "zod";
3800
+ var fields2 = ["superTitle", "title", "description"];
3801
+ var styles = {
3802
+ description: [{ attrs: { color: "base", fontSize: "small" }, type: "textStyle" }],
3803
+ superTitle: [{ attrs: { color: "subdued", fontSize: "small" }, type: "textStyle" }],
3804
+ title: [{ type: "bold" }, { attrs: { color: "base", fontSize: "large" }, type: "textStyle" }]
3805
+ };
3806
+ var settingsSchema = TextBlock.shape.settings;
3807
+ var Shell2 = z26.object({
3808
+ settings: settingsSchema.pick({ horizontalAlignment: true }).extend({
3809
+ description: z26.unknown().optional(),
3810
+ superTitle: z26.unknown().optional(),
3811
+ title: z26.unknown().optional()
3812
+ }),
3813
+ type: z26.literal("text")
3814
+ });
3815
+ var convertTextBlock = (raw, report) => {
3816
+ const shell = Shell2.safeParse(raw);
3817
+ if (!shell.success) {
3818
+ report?.({ detail: "Unreadable post-purchase text block", kind: "section" });
3819
+ return [];
3820
+ }
3821
+ const values = fields2.map((field) => ({
3822
+ field,
3823
+ result: settingsSchema.shape[field].safeParse(shell.data.settings[field])
3824
+ }));
3825
+ const horizontal = { center: "center", leading: "start", trailing: "end" }[shell.data.settings.horizontalAlignment];
3826
+ const styled = values.every(({ result }) => result.success && typeof result.data === "string");
3827
+ const omit = (field) => {
3828
+ report?.({ detail: `Unreadable post-purchase text field: ${field}`, kind: "section" });
3829
+ return [];
3830
+ };
3831
+ const sections = values.flatMap(({ field, result }) => {
3832
+ if (!result.success) return omit(field);
3833
+ const text = result.data;
3834
+ if (text === null || text === "") return [];
3835
+ const content = styled ? { content: [{ attrs: { textAlign: horizontal }, content: [{ marks: styles[field], text }] }] } : text;
3836
+ const section = CABTextSection.safeParse({ content: { en: content } });
3837
+ return section.success ? [section.data] : omit(field);
3838
+ });
3839
+ return [
3840
+ CABLayoutSection.parse({
3841
+ alignment: {
3842
+ horizontal
3843
+ },
3844
+ sections
3845
+ })
3846
+ ];
3847
+ };
3848
+
3849
+ // src/transforms/postPurchase/convertTimerBlock.ts
3850
+ var Presentation = TimerBlock.pick({ styles: true }).extend({
3851
+ settings: TimerBlock.shape.settings.pick({ title: true })
3852
+ });
3853
+ var convertTimerBlock = (raw, report) => {
3854
+ const omit = () => {
3855
+ report?.({ detail: "Unreadable post-purchase timer display", kind: "section" });
3856
+ return [];
3857
+ };
3858
+ const parsed = Presentation.safeParse(raw);
3859
+ if (!parsed.success) return omit();
3860
+ const { title } = parsed.data.settings;
3861
+ const styles2 = parsed.data.styles;
3862
+ const horizontal = { center: "center", leading: "start", trailing: "end" }[styles2.textAlignment];
3863
+ const content = typeof title === "string" ? {
3864
+ content: [
3865
+ {
3866
+ attrs: { textAlign: horizontal },
3867
+ content: [
3868
+ styledTextRun(title, styles2.titleEmphasized, styles2.titleSize),
3869
+ styledTextRun(" {{timeRemaining}}", styles2.timerEmphasized, styles2.timerSize)
3870
+ ]
3871
+ }
3872
+ ]
3873
+ } : title;
3874
+ const text = CABTextSection.safeParse({ content: { en: content } });
3875
+ if (!text.success) return omit();
3876
+ return [
3877
+ CABBannerSection.parse({
3878
+ color: styles2.timerBackgroundColor,
3879
+ dismissible: false,
3880
+ sections: [text.data],
3881
+ width: styles2.timerWidth
3882
+ })
3883
+ ];
3884
+ };
3885
+
3886
+ // src/transforms/postPurchase/convertMessagePreview.ts
3887
+ var MessageWidget = z27.object({
3888
+ blocks: z27.array(z27.unknown()).min(1),
3889
+ type: z27.literal("shopify_post_purchase_extension")
3890
+ });
3891
+ var BlockType2 = z27.object({ type: z27.string() });
3892
+ var converters = {
3893
+ callout_banner: convertCalloutBlock,
3894
+ pay_button: convertPayButtonBlock,
3895
+ separator: convertSeparatorBlock,
3896
+ text: convertTextBlock,
3897
+ timer: convertTimerBlock
3898
+ };
3899
+ var convertMessagePreview = (id, settings, report) => {
3900
+ const parsed = MessageWidget.safeParse(settings);
3901
+ if (!parsed.success) throw new NotFoundError("Unsupported post-purchase message preview");
3902
+ return CABRootSection.parse({
3903
+ editorMode: "postPurchaseOffer",
3904
+ previewMode: true,
3905
+ sections: parsed.data.blocks.flatMap((block) => {
3906
+ const type = BlockType2.safeParse(block);
3907
+ const kind = type.success ? type.data.type : void 0;
3908
+ const convert2 = kind ? converters[kind] : void 0;
3909
+ if (convert2) return convert2(block, report);
3910
+ report?.({
3911
+ detail: kind ? `Unsupported post-purchase block type: ${kind}` : "Unreadable post-purchase block: missing type",
3912
+ kind: "section"
3913
+ });
3914
+ return [];
3915
+ }),
3916
+ sectionType: "layout",
3917
+ widgetId: id
3918
+ });
3919
+ };
3920
+
3921
+ // src/transforms/postPurchase/types.ts
3922
+ var isPostPurchaseV1 = (data) => !!data && typeof data === "object" && data.type === WidgetType.shopify_post_purchase_extension && Array.isArray(data.blocks);
3923
+
3504
3924
  // src/transforms/presentmentThresholds.ts
3505
3925
  var presentmentThresholds = (presentment) => {
3506
3926
  if (!presentment?.enabled) return {};
@@ -3869,6 +4289,7 @@ export {
3869
4289
  convertContentBlockTextToV2,
3870
4290
  convertContentBlockToV2,
3871
4291
  convertLineItemEditorToV2,
4292
+ convertMessagePreview,
3872
4293
  convertMonetizeToV2,
3873
4294
  convertNumericObjects,
3874
4295
  convertOfferToV2,
@@ -3886,6 +4307,7 @@ export {
3886
4307
  isMonetizeV1,
3887
4308
  isOfferV1,
3888
4309
  isPlaceholderV1,
4310
+ isPostPurchaseV1,
3889
4311
  isProgressBarV1,
3890
4312
  normalizeTextContent,
3891
4313
  normalizeTokens,