@rebuy/rebuy 3.5.0 → 3.6.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 (40) hide show
  1. package/dist/index.cjs +740 -647
  2. package/dist/index.mjs +740 -647
  3. package/dist/schema/checkout-and-beyond/constants.cjs +16 -0
  4. package/dist/schema/checkout-and-beyond/constants.mjs +16 -0
  5. package/dist/schema/checkout-and-beyond/index.cjs +454 -362
  6. package/dist/schema/checkout-and-beyond/index.mjs +454 -362
  7. package/dist/schema/widget-data.cjs +508 -435
  8. package/dist/schema/widget-data.mjs +508 -435
  9. package/dist/schema/widgetData.d.ts +438 -147
  10. package/dist/schema/widgets/checkout-and-beyond/banner.d.ts +145 -48
  11. package/dist/schema/widgets/checkout-and-beyond/button.d.ts +154 -49
  12. package/dist/schema/widgets/checkout-and-beyond/carousel.d.ts +145 -48
  13. package/dist/schema/widgets/checkout-and-beyond/cartLine.d.ts +145 -48
  14. package/dist/schema/widgets/checkout-and-beyond/common.d.ts +29 -0
  15. package/dist/schema/widgets/checkout-and-beyond/discount.d.ts +146 -0
  16. package/dist/schema/widgets/checkout-and-beyond/icons.d.ts +1 -1
  17. package/dist/schema/widgets/checkout-and-beyond/image.d.ts +294 -100
  18. package/dist/schema/widgets/checkout-and-beyond/index.d.ts +1 -0
  19. package/dist/schema/widgets/checkout-and-beyond/layout.d.ts +148 -52
  20. package/dist/schema/widgets/checkout-and-beyond/monetize.d.ts +146 -49
  21. package/dist/schema/widgets/checkout-and-beyond/offers.d.ts +145 -48
  22. package/dist/schema/widgets/checkout-and-beyond/product.d.ts +146 -0
  23. package/dist/schema/widgets/checkout-and-beyond/products.d.ts +292 -0
  24. package/dist/schema/widgets/checkout-and-beyond/progressBar.d.ts +145 -48
  25. package/dist/schema/widgets/checkout-and-beyond/quantity.d.ts +146 -49
  26. package/dist/schema/widgets/checkout-and-beyond/reviews.d.ts +146 -49
  27. package/dist/schema/widgets/checkout-and-beyond/root.d.ts +146 -49
  28. package/dist/schema/widgets/checkout-and-beyond/rule.d.ts +140 -68
  29. package/dist/schema/widgets/checkout-and-beyond/text.d.ts +146 -49
  30. package/dist/schema/widgets/checkout-and-beyond/variables.d.ts +470 -0
  31. package/dist/schema/widgets/checkout-and-beyond/variants.d.ts +146 -49
  32. package/dist/schema/widgets/contentBlock.d.ts +146 -49
  33. package/dist/schema/widgets/lineItemEditor.d.ts +146 -49
  34. package/dist/schema/widgets/rebuyButton.d.ts +146 -49
  35. package/dist/server/index.cjs +492 -416
  36. package/dist/server/index.mjs +492 -416
  37. package/dist/transforms/index.cjs +393 -317
  38. package/dist/transforms/index.mjs +393 -317
  39. package/dist/transforms/monetizeV1/convertMonetizeToV2.d.ts +2 -2
  40. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  // src/schema/widgets/checkout-and-beyond/image.ts
2
2
  import { v7 as uuidv712 } from "uuid";
3
- import { z as z19 } from "zod";
3
+ import { z as z20 } 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])));
@@ -107,6 +107,8 @@ var languageKeys = [
107
107
  "zh"
108
108
  ];
109
109
  var LanguageKey = freezeEnum(languageKeys);
110
+ var mutatorEvents = ["item_added", "quantity_changed", "variant_selected"];
111
+ var MutatorEvent = freezeEnum(mutatorEvents);
110
112
  var objectFits = ["cover", "contain"];
111
113
  var ObjectFit = freezeEnum(objectFits);
112
114
  var popoverPositions = ["inlineStart", "inlineEnd", "blockStart", "blockEnd"];
@@ -119,6 +121,10 @@ var progressTierUnits = ["currency", "item"];
119
121
  var ProgressTierUnit = freezeEnum(progressTierUnits);
120
122
  var quantityInputs = ["select", "number"];
121
123
  var QuantityInput = freezeEnum(quantityInputs);
124
+ var resultCountOperators = ["equals", "greater_than", "less_than"];
125
+ var ResultCountOperator = freezeEnum(resultCountOperators);
126
+ var resultTagOperators = ["contains", "does_not_contain"];
127
+ var ResultTagOperator = freezeEnum(resultTagOperators);
122
128
  var reviewsSizes = ["small", "default", "large"];
123
129
  var ReviewsSize = freezeEnum(reviewsSizes);
124
130
  var sectionTypes = [
@@ -151,6 +157,8 @@ var inlineTextSizeNames = ["extraSmall", "small", "base", "medium", "large", "ex
151
157
  var InlineTextSizeName = freezeEnum(inlineTextSizeNames);
152
158
  var textSizeNames = [...inlineTextSizeNames, "heading"];
153
159
  var TextSizeName = freezeEnum(textSizeNames);
160
+ var variableEffects = ["set_false", "set_true", "toggle"];
161
+ var VariableEffect = freezeEnum(variableEffects);
154
162
  var variantModes = ["multiple", "single"];
155
163
  var VariantMode = freezeEnum(variantModes);
156
164
  var variantSelectors = ["menu", "radio", "button"];
@@ -248,6 +256,19 @@ var HEX_COLOR_REGEX = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
248
256
  var ROOT_RELATIVE_PATH_REGEX = /^\/(?!\/)/;
249
257
  var HTML_TAGS_REGEX = /<\/?[a-zA-Z][^>]*>/g;
250
258
 
259
+ // src/schema/widgets/checkout-and-beyond/shared.ts
260
+ import { z as z19 } from "zod";
261
+
262
+ // src/schema/widgets/checkout-and-beyond/banner.ts
263
+ import { z as z4 } from "zod";
264
+
265
+ // src/schema/widgets/checkout-and-beyond/layout.ts
266
+ import { v7 as uuidv7 } from "uuid";
267
+ import { z as z3 } from "zod";
268
+
269
+ // src/schema/widgets/checkout-and-beyond/variables.ts
270
+ import { z as z2 } from "zod";
271
+
251
272
  // src/schema/widgets/checkout-and-beyond/rule.ts
252
273
  import { z } from "zod";
253
274
  var ruleTypes = [
@@ -294,62 +315,108 @@ var RuleCondition = z.object({
294
315
  var RuleLogicBlock = z.object({
295
316
  rules: z.array(RuleCondition).default(() => [])
296
317
  });
297
- var CABRule = z.object({
298
- dataSourceId: z.number().nullable().default(null),
299
- enabled: z.boolean().default(false),
300
- ruleset: z.union([
301
- z.array(
302
- z.object({
303
- exitIfMatched: z.boolean().default(true),
304
- logic: z.array(RuleLogicBlock).default(() => []),
305
- output: z.array(
306
- z.object({
307
- key: z.string().default("should_show"),
308
- type: z.literal("data_json").default("data_json"),
309
- value: z.string().default("true")
310
- })
311
- ).default(() => [{ key: "should_show", type: "data_json", value: "true" }])
312
- })
313
- ),
314
- z.strictObject({}).transform(() => [])
315
- ]).default(() => [])
318
+ var CABRulesetEntry = z.object({
319
+ exitIfMatched: z.boolean().default(true),
320
+ logic: z.array(RuleLogicBlock).default(() => []),
321
+ output: z.array(
322
+ z.object({
323
+ key: z.string().default("should_show"),
324
+ type: z.literal("data_json").default("data_json"),
325
+ value: z.string().default("true")
326
+ })
327
+ ).default(() => [{ key: "should_show", type: "data_json", value: "true" }])
316
328
  });
329
+ var CABRuleset = z.union([z.array(CABRulesetEntry), z.strictObject({}).transform(() => [])]).default(() => []);
317
330
 
318
- // src/schema/widgets/checkout-and-beyond/shared.ts
319
- import { z as z18 } from "zod";
320
-
321
- // src/schema/widgets/checkout-and-beyond/banner.ts
322
- import { z as z3 } from "zod";
331
+ // src/schema/widgets/checkout-and-beyond/variables.ts
332
+ var variableEffect = z2.enum(variableEffects);
333
+ var CABVariableSeed = z2.object({
334
+ dataSourceId: z2.number().nullable().default(null),
335
+ ruleset: CABRuleset
336
+ });
337
+ var CABVariable = z2.object({
338
+ /**
339
+ * Holds until the first seed verdict lands (and forever, for unseeded variables). Omitted, it derives
340
+ * from seededness — `false` with a `seed` (visibility is EARNED), `true` without — via the transform
341
+ * below; a cross-field default has no `.default()` spelling. An explicit value always wins.
342
+ */
343
+ defaultValue: z2.boolean().optional(),
344
+ name: z2.string().min(1),
345
+ seed: CABVariableSeed.optional()
346
+ }).transform(({ defaultValue, ...variable }) => ({
347
+ defaultValue: defaultValue ?? variable.seed === void 0,
348
+ ...variable
349
+ }));
350
+ var CABVariableEffect = z2.object({
351
+ effect: variableEffect.default(VariableEffect.toggle),
352
+ variable: z2.string().min(1)
353
+ });
354
+ var CABVisibility = z2.object({
355
+ variable: z2.string().min(1),
356
+ visibleWhen: z2.boolean().default(true)
357
+ });
358
+ var resultCountOperator = z2.enum(resultCountOperators);
359
+ var resultTagOperator = z2.enum(resultTagOperators);
360
+ var mutatorEvent = z2.enum(mutatorEvents);
361
+ var CABResultCountTrigger = z2.object({
362
+ operator: resultCountOperator.default(ResultCountOperator.equals),
363
+ type: z2.literal("result_count"),
364
+ value: z2.number().default(0)
365
+ });
366
+ var CABResultTagTrigger = z2.object({
367
+ operator: resultTagOperator.default(ResultTagOperator.contains),
368
+ type: z2.literal("result_tag"),
369
+ value: z2.string().min(1)
370
+ });
371
+ var CABEventTrigger = z2.object({
372
+ event: mutatorEvent,
373
+ type: z2.literal("event")
374
+ });
375
+ var CABVariableTrigger = z2.discriminatedUnion("type", [
376
+ CABEventTrigger,
377
+ CABResultCountTrigger,
378
+ CABResultTagTrigger
379
+ ]);
380
+ var CABVariableMutator = z2.object({
381
+ effect: variableEffect.default(VariableEffect.set_false),
382
+ variable: z2.string().min(1),
383
+ when: CABVariableTrigger
384
+ });
385
+ var CABVariableFields = {
386
+ mutators: z2.array(CABVariableMutator).optional(),
387
+ variables: z2.array(CABVariable).refine((variables) => new Set(variables.map(({ name }) => name)).size === variables.length, {
388
+ message: "variable names must be unique within a section"
389
+ }).optional(),
390
+ visibility: CABVisibility.optional()
391
+ };
323
392
 
324
393
  // src/schema/widgets/checkout-and-beyond/layout.ts
325
- import { v7 as uuidv7 } from "uuid";
326
- import { z as z2 } from "zod";
327
- var GridItem = z2.union([z2.literal("auto"), z2.literal("fill"), z2.string().regex(/^\d+%$/), z2.number()]);
328
- var CABLayoutSection = z2.object({
329
- alignment: z2.object({
330
- horizontal: z2.enum(horizontalAlignments).default(HorizontalAlignment.start),
331
- vertical: z2.enum(verticalAlignments).default(VerticalAlignment.top)
394
+ var GridItem = z3.union([z3.literal("auto"), z3.literal("fill"), z3.string().regex(/^\d+%$/), z3.number()]);
395
+ var CABLayoutSection = z3.object({
396
+ ...CABVariableFields,
397
+ alignment: z3.object({
398
+ horizontal: z3.enum(horizontalAlignments).default(HorizontalAlignment.start),
399
+ vertical: z3.enum(verticalAlignments).default(VerticalAlignment.top)
332
400
  }).default({
333
401
  horizontal: HorizontalAlignment.start,
334
402
  vertical: VerticalAlignment.top
335
403
  }),
336
- border: z2.lazy(() => CABBorder),
337
- buttonField: z2.enum(buttonFields).optional(),
338
- direction: z2.enum(directions).default(Direction.rows),
339
- grid: z2.object({
340
- columns: z2.union([z2.array(GridItem), z2.undefined()]).default(() => ["auto"]),
341
- rows: z2.union([z2.array(GridItem), z2.undefined()]).default(() => ["auto"])
404
+ border: z3.lazy(() => CABBorder),
405
+ buttonField: z3.enum(buttonFields).optional(),
406
+ direction: z3.enum(directions).default(Direction.rows),
407
+ grid: z3.object({
408
+ columns: z3.union([z3.array(GridItem), z3.undefined()]).default(() => ["auto"]),
409
+ rows: z3.union([z3.array(GridItem), z3.undefined()]).default(() => ["auto"])
342
410
  }).default({ columns: ["auto"], rows: ["auto"] }).optional(),
343
- name: z2.string().optional(),
344
- padding: z2.enum(spacings).default(Spacing.none),
345
- rule: CABRule.optional(),
346
- sectionId: z2.uuid().default(() => uuidv7()),
347
- sections: z2.union([z2.array(z2.lazy(() => CABSection)), z2.strictObject({}).transform(() => [])]).default(() => []),
348
- sectionType: z2.literal(SectionType.layout).default(SectionType.layout),
349
- spacing: z2.enum(spacings).default(Spacing.base),
411
+ name: z3.string().optional(),
412
+ padding: z3.enum(spacings).default(Spacing.none),
413
+ sectionId: z3.uuid().default(() => uuidv7()),
414
+ sections: z3.union([z3.array(z3.lazy(() => CABSection)), z3.strictObject({}).transform(() => [])]).default(() => []),
415
+ sectionType: z3.literal(SectionType.layout).default(SectionType.layout),
416
+ spacing: z3.enum(spacings).default(Spacing.base),
350
417
  /** Fire-and-forget impression pixel POSTed once when the section is shown (e.g. a Monetize offer view). */
351
- viewUrl: z2.string().optional(),
352
- width: z2.number().default(100)
418
+ viewUrl: z3.string().optional(),
419
+ width: z3.number().default(100)
353
420
  });
354
421
 
355
422
  // src/schema/widgets/checkout-and-beyond/utils.ts
@@ -419,11 +486,11 @@ var isTextType = isSectionType(SectionType.text);
419
486
  var isVariantsType = isSectionType(SectionType.variants);
420
487
 
421
488
  // src/schema/widgets/checkout-and-beyond/banner.ts
422
- var CABBannerSection = z3.lazy(
489
+ var CABBannerSection = z4.lazy(
423
490
  () => CABLayoutSection.omit({ sectionType: true }).extend({
424
- buttonField: z3.enum(buttonFields).optional(),
425
- color: z3.enum(bannerColors).default("info"),
426
- dismissible: z3.boolean().default(true),
491
+ buttonField: z4.enum(buttonFields).optional(),
492
+ color: z4.enum(bannerColors).default("info"),
493
+ dismissible: z4.boolean().default(true),
427
494
  /**
428
495
  * The `s-banner` heading — localized content (a buyer can see a merchant-composed banner). Absent OR
429
496
  * blank ⇒ no heading; the renderer emits no heading slot for `''` rather than an empty one.
@@ -439,83 +506,83 @@ var CABBannerSection = z3.lazy(
439
506
  * not a 500. Nothing emits `heading` yet; the first converter that maps merchant banner copy into it
440
507
  * either strips first or teaches `normalizeTextContent` to strip this field.
441
508
  */
442
- heading: z3.record(z3.string(), z3.string().refine(checkForHTML, NO_HTML)).optional(),
443
- sectionType: z3.literal(SectionType.banner).default(SectionType.banner)
509
+ heading: z4.record(z4.string(), z4.string().refine(checkForHTML, NO_HTML)).optional(),
510
+ sectionType: z4.literal(SectionType.banner).default(SectionType.banner)
444
511
  })
445
512
  );
446
513
 
447
514
  // src/schema/widgets/checkout-and-beyond/button.ts
448
515
  import { v7 as uuidv73 } from "uuid";
449
- import { z as z5 } from "zod";
516
+ import { z as z6 } from "zod";
450
517
 
451
518
  // src/schema/widgets/checkout-and-beyond/text.ts
452
519
  import { forEach, isString as isString2 } from "es-toolkit/compat";
453
520
  import { v7 as uuidv72 } from "uuid";
454
- import { z as z4 } from "zod";
455
- var enumOrOmit = (...vals) => z4.string().transform((val) => vals.includes(val) ? val : void 0).optional();
456
- var TiptapText = z4.object({
457
- marks: z4.union([
458
- z4.array(
459
- z4.discriminatedUnion("type", [
460
- z4.object({ type: z4.literal("bold") }),
461
- z4.object({ type: z4.literal("italic") }),
462
- z4.object({
463
- attrs: z4.object({
464
- class: z4.string().nullable(),
465
- href: z4.union([
466
- z4.url(),
467
- z4.literal("#"),
468
- z4.string().regex(DYNAMIC_TOKEN_REGEX),
469
- z4.string().regex(ROOT_RELATIVE_PATH_REGEX)
521
+ import { z as z5 } from "zod";
522
+ var enumOrOmit = (...vals) => z5.string().transform((val) => vals.includes(val) ? val : void 0).optional();
523
+ var TiptapText = z5.object({
524
+ marks: z5.union([
525
+ z5.array(
526
+ z5.discriminatedUnion("type", [
527
+ z5.object({ type: z5.literal("bold") }),
528
+ z5.object({ type: z5.literal("italic") }),
529
+ z5.object({
530
+ attrs: z5.object({
531
+ class: z5.string().nullable(),
532
+ href: z5.union([
533
+ z5.url(),
534
+ z5.literal("#"),
535
+ z5.string().regex(DYNAMIC_TOKEN_REGEX),
536
+ z5.string().regex(ROOT_RELATIVE_PATH_REGEX)
470
537
  ]),
471
- rel: z4.string().default("noopener noreferrer nofollow"),
472
- target: z4.string().default("_blank")
538
+ rel: z5.string().default("noopener noreferrer nofollow"),
539
+ target: z5.string().default("_blank")
473
540
  }),
474
- type: z4.literal("link")
541
+ type: z5.literal("link")
475
542
  }),
476
- z4.object({ type: z4.literal("strike") }),
477
- z4.object({
478
- attrs: z4.object({
543
+ z5.object({ type: z5.literal("strike") }),
544
+ z5.object({
545
+ attrs: z5.object({
479
546
  color: enumOrOmit(...textColorNames).default(TextColorName.base),
480
547
  fontSize: enumOrOmit(...textSizeNames).default(TextSizeName.base)
481
548
  }),
482
- type: z4.literal("textStyle")
549
+ type: z5.literal("textStyle")
483
550
  })
484
551
  ])
485
552
  ),
486
- z4.strictObject({}).transform(() => [])
553
+ z5.strictObject({}).transform(() => [])
487
554
  ]).optional(),
488
- text: z4.string().default(""),
489
- type: z4.literal("text").default("text")
555
+ text: z5.string().default(""),
556
+ type: z5.literal("text").default("text")
490
557
  });
491
- var TiptapParagraph = z4.object({
492
- attrs: z4.object({
558
+ var TiptapParagraph = z5.object({
559
+ attrs: z5.object({
493
560
  textAlign: enumOrOmit(...textAlignments)
494
561
  }).default({ textAlign: TextAlignment.start }),
495
- content: z4.union([z4.array(TiptapText), z4.strictObject({}).transform(() => [])]).default(() => []),
496
- type: z4.literal("paragraph").default("paragraph")
562
+ content: z5.union([z5.array(TiptapText), z5.strictObject({}).transform(() => [])]).default(() => []),
563
+ type: z5.literal("paragraph").default("paragraph")
497
564
  });
498
- var TiptapDocument = z4.object({
499
- attrs: z4.object({
565
+ var TiptapDocument = z5.object({
566
+ attrs: z5.object({
500
567
  blockSpacing: enumOrOmit(...spacings)
501
568
  }).default({ blockSpacing: Spacing.base }),
502
- content: z4.union([z4.array(TiptapParagraph), z4.strictObject({}).transform(() => [])]).default(() => [TiptapParagraph.parse({})]),
503
- type: z4.literal("doc").default("doc")
569
+ content: z5.union([z5.array(TiptapParagraph), z5.strictObject({}).transform(() => [])]).default(() => [TiptapParagraph.parse({})]),
570
+ type: z5.literal("doc").default("doc")
504
571
  });
505
- var CABTextTier = z4.object({
506
- threshold: z4.number().int().nonnegative(),
507
- thresholds: z4.record(z4.string(), z4.number().int().nonnegative()).default(() => ({})),
508
- tierId: z4.string().optional(),
509
- tierType: z4.enum(progressTierTypes).default(ProgressTierType.shipping)
572
+ var CABTextTier = z5.object({
573
+ threshold: z5.number().int().nonnegative(),
574
+ thresholds: z5.record(z5.string(), z5.number().int().nonnegative()).default(() => ({})),
575
+ tierId: z5.string().optional(),
576
+ tierType: z5.enum(progressTierTypes).default(ProgressTierType.shipping)
510
577
  });
511
- var CABTextSection = z4.object({
512
- buttonField: z4.enum(buttonFields).optional(),
513
- content: z4.record(z4.string(), z4.union([z4.string(), TiptapDocument]).refine(checkForHTML, NO_HTML).optional()).default({ en: TiptapDocument.parse({}) }).optional(),
514
- name: z4.string().optional(),
515
- optionId: z4.number().optional(),
516
- rule: CABRule.optional(),
517
- sectionId: z4.uuid().default(() => uuidv72()),
518
- sectionType: z4.literal(SectionType.text).default(SectionType.text),
578
+ var CABTextSection = z5.object({
579
+ ...CABVariableFields,
580
+ buttonField: z5.enum(buttonFields).optional(),
581
+ content: z5.record(z5.string(), z5.union([z5.string(), TiptapDocument]).refine(checkForHTML, NO_HTML).optional()).default({ en: TiptapDocument.parse({}) }).optional(),
582
+ name: z5.string().optional(),
583
+ optionId: z5.number().optional(),
584
+ sectionId: z5.uuid().default(() => uuidv72()),
585
+ sectionType: z5.literal(SectionType.text).default(SectionType.text),
519
586
  tier: CABTextTier.optional()
520
587
  }).superRefine(({ buttonField, content }, ctx) => {
521
588
  if (buttonField === ButtonField.destinationUrl && content) {
@@ -537,35 +604,35 @@ var CABTextSection = z4.object({
537
604
  });
538
605
 
539
606
  // src/schema/widgets/checkout-and-beyond/button.ts
540
- var CABButtonContent = z5.lazy(
541
- () => z5.discriminatedUnion("sectionType", [CABImageSection, CABLayoutSection, CABTextSection])
607
+ var CABButtonContent = z6.lazy(
608
+ () => z6.discriminatedUnion("sectionType", [CABImageSection, CABLayoutSection, CABTextSection])
542
609
  );
543
- var CABButtonSection = z5.object({
544
- action: z5.union([z5.literal(""), z5.enum(buttonActions)]).default(""),
545
- buttonStyle: z5.enum(buttonStyles).default(ButtonStyle.primary),
546
- custom: z5.object({
547
- color: z5.string().regex(HEX_COLOR_REGEX).default("#005bd3"),
548
- height: z5.number().default(52),
549
- width: z5.number().default(300)
610
+ var CABButtonSection = z6.object({
611
+ ...CABVariableFields,
612
+ action: z6.union([z6.literal(""), z6.enum(buttonActions)]).default(""),
613
+ buttonStyle: z6.enum(buttonStyles).default(ButtonStyle.primary),
614
+ custom: z6.object({
615
+ color: z6.string().regex(HEX_COLOR_REGEX).default("#005bd3"),
616
+ height: z6.number().default(52),
617
+ width: z6.number().default(300)
550
618
  }).default({
551
619
  color: "#005bd3",
552
620
  height: 52,
553
621
  width: 300
554
622
  }),
555
- disableDowngrade: z5.boolean().default(false),
556
- name: z5.string().optional(),
557
- optionId: z5.number().optional(),
558
- popover: z5.object({
559
- alignment: z5.enum(textAlignments).default(TextAlignment.center),
560
- position: z5.enum(popoverPositions).default(PopoverPosition.blockStart)
623
+ disableDowngrade: z6.boolean().default(false),
624
+ name: z6.string().optional(),
625
+ optionId: z6.number().optional(),
626
+ popover: z6.object({
627
+ alignment: z6.enum(textAlignments).default(TextAlignment.center),
628
+ position: z6.enum(popoverPositions).default(PopoverPosition.blockStart)
561
629
  }).optional().default(() => ({
562
630
  alignment: TextAlignment.center,
563
631
  position: PopoverPosition.blockStart
564
632
  })),
565
- rule: CABRule.optional(),
566
- sectionId: z5.uuid().default(() => uuidv73()),
567
- sections: z5.union([z5.array(CABButtonContent), z5.strictObject({}).transform(() => [])]).default(() => []),
568
- sectionType: z5.literal(SectionType.button).default(SectionType.button),
633
+ sectionId: z6.uuid().default(() => uuidv73()),
634
+ sections: z6.union([z6.array(CABButtonContent), z6.strictObject({}).transform(() => [])]).default(() => []),
635
+ sectionType: z6.literal(SectionType.button).default(SectionType.button),
569
636
  /**
570
637
  * The smart-cart tier this button acts on (`addGift`/`removeGift`): scopes the click to one tier's gift. The
571
638
  * client resolves the tier's gift (productId) from the progress-bar context by this `tierId` — the button node
@@ -580,20 +647,25 @@ var CABButtonSection = z5.object({
580
647
  * lookup finds no tier and the click resolves to nothing. Safe to bound — the field is new, so there are no
581
648
  * stored payloads to grandfather, and the producer is client code, not a merchant form.
582
649
  */
583
- tier: z5.object({ tierId: z5.string().min(1) }).optional(),
650
+ tier: z6.object({ tierId: z6.string().min(1) }).optional(),
584
651
  /** Fire-and-forget pixel POSTed when the button is clicked (e.g. a Monetize decline). */
585
- trackingUrl: z5.string().optional()
652
+ trackingUrl: z6.string().optional(),
653
+ /**
654
+ * Secondary effects applied to in-scope variables on click, alongside (never instead of) the primary
655
+ * `action` — an `addToOrder` button can also flip a variable. Applied in array order.
656
+ */
657
+ variableEffects: z6.array(CABVariableEffect).optional()
586
658
  });
587
659
 
588
660
  // src/schema/widgets/checkout-and-beyond/carousel.ts
589
- import { z as z10 } from "zod";
661
+ import { z as z11 } from "zod";
590
662
 
591
663
  // src/schema/widgets/checkout-and-beyond/offers.ts
592
- import { z as z9 } from "zod";
664
+ import { z as z10 } from "zod";
593
665
 
594
666
  // src/schema/widgets/checkout-and-beyond/dataSource.ts
595
667
  import { v7 as uuidv74 } from "uuid";
596
- import { z as z6 } from "zod";
668
+ import { z as z7 } from "zod";
597
669
 
598
670
  // src/schema/widgets/checkout-and-beyond/constants.ts
599
671
  import { uniqBy } from "es-toolkit";
@@ -672,72 +744,74 @@ var widgetTypes = [
672
744
  var WidgetType = freezeEnum(widgetTypes);
673
745
 
674
746
  // src/schema/widgets/checkout-and-beyond/dataSource.ts
675
- var CABDiscount = z6.object({
676
- amount: z6.union([z6.number(), z6.string()]).catch(0),
677
- discountedBy: z6.string().optional(),
678
- discountedFrom: z6.enum(discountSources).optional().catch(void 0),
679
- type: z6.enum(discountTypes).catch("none")
747
+ var CABDiscount = z7.object({
748
+ amount: z7.union([z7.number(), z7.string()]).catch(0),
749
+ discountedBy: z7.string().optional(),
750
+ discountedFrom: z7.enum(discountSources).optional().catch(void 0),
751
+ type: z7.enum(discountTypes).catch("none")
680
752
  });
681
- var CABIntegrations = z6.object({
682
- judgeme: z6.boolean().default(false),
683
- junip: z6.boolean().default(false),
684
- klaviyo: z6.boolean().default(false),
685
- loox: z6.boolean().default(false),
686
- okendo: z6.boolean().default(false),
687
- opinew: z6.boolean().default(false),
688
- reviewsio: z6.boolean().default(false),
689
- stamped: z6.boolean().default(false),
690
- yotpo: z6.boolean().default(false)
753
+ var CABIntegrations = z7.object({
754
+ judgeme: z7.boolean().default(false),
755
+ junip: z7.boolean().default(false),
756
+ klaviyo: z7.boolean().default(false),
757
+ loox: z7.boolean().default(false),
758
+ okendo: z7.boolean().default(false),
759
+ opinew: z7.boolean().default(false),
760
+ reviewsio: z7.boolean().default(false),
761
+ stamped: z7.boolean().default(false),
762
+ yotpo: z7.boolean().default(false)
691
763
  });
692
- var CABDataSourceSection = z6.object({
693
- dataSourceId: z6.number().nullable().default(null),
694
- dataSourcePath: z6.string().default(DEFAULT_ENDPOINTS[0].value),
764
+ var CABDataSourceSection = z7.object({
765
+ dataSourceId: z7.number().nullable().default(null),
766
+ dataSourcePath: z7.string().default(DEFAULT_ENDPOINTS[0].value),
695
767
  discount: CABDiscount.optional(),
696
768
  integrations: CABIntegrations.optional(),
697
- limit: z6.number().default(1),
698
- matchVariant: z6.boolean().default(false),
699
- matchVariantOutOfStock: z6.boolean().default(false),
700
- name: z6.string().default(DEFAULT_ENDPOINTS[0].label),
701
- productType: z6.enum(productTypes).optional(),
702
- sectionId: z6.uuid().default(() => uuidv74()),
703
- sectionType: z6.literal(SectionType.dataSource).default(SectionType.dataSource),
769
+ limit: z7.number().default(1),
770
+ matchVariant: z7.boolean().default(false),
771
+ matchVariantOutOfStock: z7.boolean().default(false),
772
+ name: z7.string().default(DEFAULT_ENDPOINTS[0].label),
773
+ productType: z7.enum(productTypes).optional(),
774
+ sectionId: z7.uuid().default(() => uuidv74()),
775
+ sectionType: z7.literal(SectionType.dataSource).default(SectionType.dataSource),
704
776
  /** Default subscribe-vs-one-time for `productType: both` (legacy `subscription_is_default`). */
705
- subscriptionIsDefault: z6.boolean().default(false),
706
- treatAsGwp: z6.boolean().default(false)
777
+ subscriptionIsDefault: z7.boolean().default(false),
778
+ treatAsGwp: z7.boolean().default(false)
707
779
  });
708
780
 
709
781
  // src/schema/widgets/checkout-and-beyond/products.ts
710
782
  import { v7 as uuidv76 } from "uuid";
711
- import { z as z8 } from "zod";
783
+ import { z as z9 } from "zod";
712
784
 
713
785
  // src/schema/widgets/checkout-and-beyond/product.ts
714
786
  import { v7 as uuidv75 } from "uuid";
715
- import { z as z7 } from "zod";
716
- var CABVariantContent = z7.lazy(
717
- () => z7.discriminatedUnion("sectionType", [CABButtonSection, CABTextSection])
787
+ import { z as z8 } from "zod";
788
+ var CABVariantContent = z8.lazy(
789
+ () => z8.discriminatedUnion("sectionType", [CABButtonSection, CABTextSection])
718
790
  );
719
- var CABProductSection = z7.object({
720
- name: z7.string().optional(),
721
- productId: z7.number().nullable().default(null),
722
- sectionId: z7.uuid().default(() => uuidv75()),
723
- sections: z7.union([z7.array(CABVariantContent), z7.strictObject({}).transform(() => [])]).default(() => []),
724
- sectionType: z7.literal(SectionType.product).default(SectionType.product),
725
- selectors: z7.record(z7.string(), z7.enum(variantSelectors).default(VariantSelector.menu)).default(() => ({})),
726
- variantMode: z7.enum(variantModes).default(VariantMode.multiple)
791
+ var CABProductSection = z8.object({
792
+ ...CABVariableFields,
793
+ name: z8.string().optional(),
794
+ productId: z8.number().nullable().default(null),
795
+ sectionId: z8.uuid().default(() => uuidv75()),
796
+ sections: z8.union([z8.array(CABVariantContent), z8.strictObject({}).transform(() => [])]).default(() => []),
797
+ sectionType: z8.literal(SectionType.product).default(SectionType.product),
798
+ selectors: z8.record(z8.string(), z8.enum(variantSelectors).default(VariantSelector.menu)).default(() => ({})),
799
+ variantMode: z8.enum(variantModes).default(VariantMode.multiple)
727
800
  });
728
801
 
729
802
  // src/schema/widgets/checkout-and-beyond/products.ts
730
- var CABProductsSection = z8.object({
731
- name: z8.string().optional(),
732
- sectionId: z8.uuid().default(() => uuidv76()),
733
- sections: z8.union([z8.array(z8.lazy(() => CABProductSection)), z8.strictObject({}).transform(() => [])]).default(() => []),
734
- sectionType: z8.literal(SectionType.products).default(SectionType.products)
803
+ var CABProductsSection = z9.object({
804
+ ...CABVariableFields,
805
+ name: z9.string().optional(),
806
+ sectionId: z9.uuid().default(() => uuidv76()),
807
+ sections: z9.union([z9.array(z9.lazy(() => CABProductSection)), z9.strictObject({}).transform(() => [])]).default(() => []),
808
+ sectionType: z9.literal(SectionType.products).default(SectionType.products)
735
809
  });
736
810
 
737
811
  // src/schema/widgets/checkout-and-beyond/offers.ts
738
- var CABOffersSection = z9.lazy(
812
+ var CABOffersSection = z10.lazy(
739
813
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
740
- sections: z9.union([z9.array(z9.lazy(() => CABSection)), z9.strictObject({}).transform(() => [])]).default(() => [
814
+ sections: z10.union([z10.array(z10.lazy(() => CABSection)), z10.strictObject({}).transform(() => [])]).default(() => [
741
815
  CABBannerSection.parse({
742
816
  buttonField: "undoAddToOrder",
743
817
  color: "success",
@@ -751,64 +825,65 @@ var CABOffersSection = z9.lazy(
751
825
  CABDataSourceSection.parse({}),
752
826
  CABProductsSection.parse({})
753
827
  ]),
754
- sectionType: z9.literal(SectionType.offers).default(SectionType.offers)
828
+ sectionType: z10.literal(SectionType.offers).default(SectionType.offers)
755
829
  })
756
830
  );
757
831
 
758
832
  // src/schema/widgets/checkout-and-beyond/carousel.ts
759
- var CABCarouselSection = z10.lazy(
833
+ var CABCarouselSection = z11.lazy(
760
834
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
761
- autoAdvanceInterval: z10.number().default(0),
762
- itemsAtOnce: z10.number().min(1).default(1),
835
+ autoAdvanceInterval: z11.number().default(0),
836
+ itemsAtOnce: z11.number().min(1).default(1),
763
837
  /** Card arrangement for the offers child (`horizontal` = side-by-side) — NOT the carousel's own `direction`. */
764
- offersDirection: z10.enum(offersDirections).default("vertical"),
765
- sections: z10.union([z10.array(z10.lazy(() => CABSection)), z10.strictObject({}).transform(() => [])]).default(() => [CABOffersSection.parse({})]),
766
- sectionType: z10.literal(SectionType.carousel).default(SectionType.carousel)
838
+ offersDirection: z11.enum(offersDirections).default("vertical"),
839
+ sections: z11.union([z11.array(z11.lazy(() => CABSection)), z11.strictObject({}).transform(() => [])]).default(() => [CABOffersSection.parse({})]),
840
+ sectionType: z11.literal(SectionType.carousel).default(SectionType.carousel)
767
841
  })
768
842
  );
769
843
 
770
844
  // src/schema/widgets/checkout-and-beyond/cartLine.ts
771
- import { z as z11 } from "zod";
772
- var CABCartLineSection = z11.lazy(
845
+ import { z as z12 } from "zod";
846
+ var CABCartLineSection = z12.lazy(
773
847
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
774
- sections: z11.union([z11.array(z11.lazy(() => CABSection)), z11.strictObject({}).transform(() => [])]).default(() => [CABButtonSection.parse({ action: ButtonAction.switchToSubscription })]),
775
- sectionType: z11.literal(SectionType.cartLine).default(SectionType.cartLine)
848
+ sections: z12.union([z12.array(z12.lazy(() => CABSection)), z12.strictObject({}).transform(() => [])]).default(() => [CABButtonSection.parse({ action: ButtonAction.switchToSubscription })]),
849
+ sectionType: z12.literal(SectionType.cartLine).default(SectionType.cartLine)
776
850
  })
777
851
  );
778
852
 
779
853
  // src/schema/widgets/checkout-and-beyond/discount.ts
780
854
  import { v7 as uuidv77 } from "uuid";
781
- import { z as z12 } from "zod";
782
- var CABDiscountSection = z12.object({
783
- amount: z12.union([z12.number(), z12.string()]).catch(0),
784
- discountedBy: z12.string().optional(),
785
- discountedFrom: z12.enum(discountSources).optional().catch(void 0),
786
- message: z12.string().optional(),
787
- name: z12.string().optional(),
788
- quantity: z12.number().default(1),
789
- sectionId: z12.uuid().default(() => uuidv77()),
790
- sectionType: z12.literal(SectionType.discount).default(SectionType.discount),
791
- type: z12.enum(discountTypes).catch("none")
855
+ import { z as z13 } from "zod";
856
+ var CABDiscountSection = z13.object({
857
+ ...CABVariableFields,
858
+ amount: z13.union([z13.number(), z13.string()]).catch(0),
859
+ discountedBy: z13.string().optional(),
860
+ discountedFrom: z13.enum(discountSources).optional().catch(void 0),
861
+ message: z13.string().optional(),
862
+ name: z13.string().optional(),
863
+ quantity: z13.number().default(1),
864
+ sectionId: z13.uuid().default(() => uuidv77()),
865
+ sectionType: z13.literal(SectionType.discount).default(SectionType.discount),
866
+ type: z13.enum(discountTypes).catch("none")
792
867
  });
793
868
 
794
869
  // src/schema/widgets/checkout-and-beyond/monetize.ts
795
870
  import { v7 as uuidv78 } from "uuid";
796
- import { z as z13 } from "zod";
797
- var CABMonetizeSection = z13.object({
798
- name: z13.string().optional(),
871
+ import { z as z14 } from "zod";
872
+ var CABMonetizeSection = z14.object({
873
+ ...CABVariableFields,
874
+ name: z14.string().optional(),
799
875
  /** Privacy Policy footer href (the widget's `privacy_policy_url` setting); the client relays it to `/cab/monetize`. */
800
- privacyPolicyUrl: z13.string().optional(),
801
- rule: CABRule.optional(),
802
- sectionId: z13.uuid().default(() => uuidv78()),
803
- sectionType: z13.literal(SectionType.monetize).default(SectionType.monetize),
876
+ privacyPolicyUrl: z14.string().optional(),
877
+ sectionId: z14.uuid().default(() => uuidv78()),
878
+ sectionType: z14.literal(SectionType.monetize).default(SectionType.monetize),
804
879
  /** Ads-taxonomy sub-vertical id (the widget's `sub_vertical` setting); paired with `vertical`. */
805
- subVertical: z13.string().optional(),
880
+ subVertical: z14.string().optional(),
806
881
  /** Ads-taxonomy vertical id (the widget's `vertical` setting) — with `subVertical`, the admin Monetize editor's two configurables. */
807
- vertical: z13.string().optional()
882
+ vertical: z14.string().optional()
808
883
  });
809
884
 
810
885
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
811
- import { z as z14 } from "zod";
886
+ import { z as z15 } from "zod";
812
887
 
813
888
  // src/schema/widgets/checkout-and-beyond/giftLabels.ts
814
889
  var GIFT_LABELS = {
@@ -927,21 +1002,21 @@ var GIFT_LABELS = {
927
1002
  };
928
1003
 
929
1004
  // src/schema/widgets/checkout-and-beyond/progressBar.ts
930
- var CABProgressTier = z14.object({
1005
+ var CABProgressTier = z15.object({
931
1006
  /**
932
1007
  * Order-discount tiers only (onsite `discount`): the reward the order-discount Function applies at
933
1008
  * cart time, carried so the client can resolve the `{{discountAmount}}` token in this tier's copy.
934
1009
  * `fixedAmount`: shop-currency CENTS (FX-scaled by the client, like {@link CABProgressTier.threshold});
935
1010
  * `percentage`: the whole-percent number rendered raw (`{n}%`). Absent on non-discount tiers.
936
1011
  */
937
- discount: z14.object({ amount: z14.number().nonnegative(), type: z14.enum(["fixedAmount", "percentage"]) }).optional(),
1012
+ discount: z15.object({ amount: z15.number().nonnegative(), type: z15.enum(["fixedAmount", "percentage"]) }).optional(),
938
1013
  /**
939
1014
  * Smart-cart product (gift) tiers only (onsite `filter_oos_variants`): when set, the client drops this
940
1015
  * tier entirely once its gift has NO in-stock eligible variant — the milestone, fill slot and gift
941
1016
  * controls all disappear, mirroring onsite removing the tier from `bar.tiers` before it renders. Absent
942
1017
  * on shipping/discount/decorative tiers and left off by default (the tier renders regardless of stock).
943
1018
  */
944
- filterOosVariants: z14.boolean().default(false),
1019
+ filterOosVariants: z15.boolean().default(false),
945
1020
  /**
946
1021
  * Smart-cart product (gift) tiers only: the reward unlocked at this tier. The client enriches
947
1022
  * `productId`/`variantIds` to live variants (availability, price) and adds the chosen one to the cart
@@ -949,10 +1024,10 @@ var CABProgressTier = z14.object({
949
1024
  * tiers and on tiers with no configured product. Cart add/remove is a later stage; carried here so the
950
1025
  * tree is complete.
951
1026
  */
952
- gift: z14.object({
953
- productId: z14.number().int().positive(),
954
- title: z14.string().optional(),
955
- variantIds: z14.array(z14.number().int().positive()).default(() => [])
1027
+ gift: z15.object({
1028
+ productId: z15.number().int().positive(),
1029
+ title: z15.string().optional(),
1030
+ variantIds: z15.array(z15.number().int().positive()).default(() => [])
956
1031
  }).optional(),
957
1032
  /**
958
1033
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
@@ -963,35 +1038,35 @@ var CABProgressTier = z14.object({
963
1038
  * turns a blank label into an absent key, and a client-authored blank means the same thing — the renderer
964
1039
  * emits no caption slot rather than an empty one). Plain text — a compact icon+label.
965
1040
  */
966
- label: z14.record(z14.string(), z14.string()).optional(),
1041
+ label: z15.record(z15.string(), z15.string()).optional(),
967
1042
  /**
968
1043
  * Smart-cart product (gift) tiers only (onsite `product_tier_image`): show the gift's product image in
969
1044
  * the step-row slot instead of the generic bag icon. The converter can't supply the image URL (config
970
1045
  * carries only product IDs), so the client resolves it (authoritative Shopify featured image, React
971
1046
  * parity) and falls back to the bag icon when the flag is off or no image resolves. Default false.
972
1047
  */
973
- productTierImage: z14.boolean().default(false),
1048
+ productTierImage: z15.boolean().default(false),
974
1049
  /**
975
1050
  * The tier's goal, measured per `unit`. `currency` (default): SHOP-currency cents — the canonical
976
1051
  * fallback: when the buyer's presentment currency has no entry in `thresholds`, the client
977
1052
  * multiplies this by the live FX rate (converter maps the v1 `unlock_price`, e.g. `75` → `7500`).
978
1053
  * `item`: a raw item count — no cents, no FX, no `thresholds` overrides.
979
1054
  */
980
- threshold: z14.number().int().nonnegative(),
1055
+ threshold: z15.number().int().nonnegative(),
981
1056
  /**
982
1057
  * Per-presentment-currency goal overrides — lowercased ISO currency code → cents (e.g. `{ cad: 9900 }`).
983
1058
  * When the buyer's currency has an entry, the client uses it verbatim INSTEAD of FX-converting
984
1059
  * `threshold`, so merchants show intentional, clean per-market amounts (Shopify Markets) rather than a
985
1060
  * converted base. Defaults to `{}` — no overrides means always fall back to `threshold`.
986
1061
  */
987
- thresholds: z14.record(z14.string(), z14.number().int().nonnegative()).default(() => ({})),
1062
+ thresholds: z15.record(z15.string(), z15.number().int().nonnegative()).default(() => ({})),
988
1063
  /**
989
1064
  * Smart-cart tier identifier, mirrored onto the gift cart line's `_tier` attribute so the client can
990
1065
  * match an in-cart gift back to its tier (add on reach, remove on downgrade/decline). Absent on the
991
1066
  * shipping bar (single unlabeled tier, no gift).
992
1067
  */
993
- tierId: z14.string().optional(),
994
- tierType: z14.enum(progressTierTypes).default(ProgressTierType.shipping),
1068
+ tierId: z15.string().optional(),
1069
+ tierType: z15.enum(progressTierTypes).default(ProgressTierType.shipping),
995
1070
  /**
996
1071
  * What this tier's progress is measured in — PER TIER (onsite's `unlock_condition_type` model, NOT
997
1072
  * the React port's bar-level `tiers[0]` shortcut). `currency` compares money cents against the
@@ -1002,9 +1077,9 @@ var CABProgressTier = z14.object({
1002
1077
  * count carries no injected noun (no English `item`/`items` inflection on localized copy); merchant
1003
1078
  * template text supplies grammatically-neutral wording around the token.
1004
1079
  */
1005
- unit: z14.enum(progressTierUnits).default(ProgressTierUnit.currency)
1080
+ unit: z15.enum(progressTierUnits).default(ProgressTierUnit.currency)
1006
1081
  });
1007
- var CABProgressBarSection = z14.lazy(
1082
+ var CABProgressBarSection = z15.lazy(
1008
1083
  () => CABLayoutSection.omit({ sectionType: true }).extend({
1009
1084
  /**
1010
1085
  * The onsite bar id (smart-cart TPB bars only). The client mirrors it to the cart's `_barId` attribute
@@ -1013,35 +1088,35 @@ var CABProgressBarSection = z14.lazy(
1013
1088
  * checkout reaches the extension without it, so the client writes it or the tier gift's 100% discount
1014
1089
  * (and any tier order discount) never applies. Absent on the v1 shipping bar (no gift tiers, no id).
1015
1090
  */
1016
- barId: z14.string().optional(),
1091
+ barId: z15.string().optional(),
1017
1092
  /** Empty = shown everywhere; otherwise uppercase ISO country codes. */
1018
- countryCodes: z14.array(z14.string().transform((code) => code.trim().toUpperCase())).default(() => []),
1093
+ countryCodes: z15.array(z15.string().transform((code) => code.trim().toUpperCase())).default(() => []),
1019
1094
  /**
1020
1095
  * Uppercase ISO codes where a higher-precedence geo bar applies, so this (default, non-geo) bar is
1021
1096
  * hidden there — replicates React `getbar`'s geo-match-over-default precedence. Empty = never excluded.
1022
1097
  */
1023
- excludeCountryCodes: z14.array(z14.string().transform((code) => code.trim().toUpperCase())).default(() => []),
1098
+ excludeCountryCodes: z15.array(z15.string().transform((code) => code.trim().toUpperCase())).default(() => []),
1024
1099
  /**
1025
1100
  * Measure progress against the PRE-discount subtotal (onsite `exclude_discount_in_subtotal`, and
1026
1101
  * forced on for bars with a discount tier so its own reward can't un-reach the tier). The client
1027
1102
  * adds the cart's discount allocations back to the live subtotal.
1028
1103
  */
1029
- excludeDiscountInSubtotal: z14.boolean().default(false),
1104
+ excludeDiscountInSubtotal: z15.boolean().default(false),
1030
1105
  /** Variant ids the client subtracts from the adjusted subtotal (React `bar.excluded_products`). */
1031
- excludedVariantIds: z14.array(z14.number().int().positive()).default(() => []),
1106
+ excludedVariantIds: z15.array(z15.number().int().positive()).default(() => []),
1032
1107
  /**
1033
1108
  * When the cart holds a subscription item, treat the bar as reached regardless of subtotal (React
1034
1109
  * `free_shipping_on_subscription(s)`). `freeShippingOnAll` is already a zero-threshold tier instead.
1035
1110
  */
1036
- freeShippingOnSubscription: z14.boolean().default(false),
1111
+ freeShippingOnSubscription: z15.boolean().default(false),
1037
1112
  /** Localized heading over the gift controls (onsite `gift_area_title`, default 'FREE GIFTS'). */
1038
- giftAreaTitle: z14.record(z14.string(), z14.string()).default(() => ({ en: "FREE GIFTS" })),
1113
+ giftAreaTitle: z15.record(z15.string(), z15.string()).default(() => ({ en: "FREE GIFTS" })),
1039
1114
  /** Localized gift-control labels (add/remove/heading); a tier's gift `title` beats `yourGift`. */
1040
- giftLabels: z14.object({
1041
- addGift: z14.record(z14.string(), z14.string()).default(() => ({ ...GIFT_LABELS.addGift })),
1042
- remove: z14.record(z14.string(), z14.string()).default(() => ({ ...GIFT_LABELS.remove })),
1043
- selectOptions: z14.record(z14.string(), z14.string()).default(() => ({ ...GIFT_LABELS.selectOptions })),
1044
- yourGift: z14.record(z14.string(), z14.string()).default(() => ({ ...GIFT_LABELS.yourGift }))
1115
+ giftLabels: z15.object({
1116
+ addGift: z15.record(z15.string(), z15.string()).default(() => ({ ...GIFT_LABELS.addGift })),
1117
+ remove: z15.record(z15.string(), z15.string()).default(() => ({ ...GIFT_LABELS.remove })),
1118
+ selectOptions: z15.record(z15.string(), z15.string()).default(() => ({ ...GIFT_LABELS.selectOptions })),
1119
+ yourGift: z15.record(z15.string(), z15.string()).default(() => ({ ...GIFT_LABELS.yourGift }))
1045
1120
  }).default(() => ({
1046
1121
  addGift: { ...GIFT_LABELS.addGift },
1047
1122
  remove: { ...GIFT_LABELS.remove },
@@ -1049,37 +1124,38 @@ var CABProgressBarSection = z14.lazy(
1049
1124
  yourGift: { ...GIFT_LABELS.yourGift }
1050
1125
  })),
1051
1126
  /** The bar's a11y label; the merchant names it in the editor, else this default (React parity). */
1052
- name: z14.string().default("Order progress"),
1127
+ name: z15.string().default("Order progress"),
1053
1128
  /**
1054
1129
  * Bar fill color. An explicit (widget-authored) value is used verbatim; when absent the server
1055
1130
  * fills it with the live shop theme's `buttonBackground` (React `useRebuyTheme` parity). Still
1056
1131
  * absent after that ⇒ the theme fetch failed and the client renders its platform-default bar —
1057
1132
  * optional, not defaulted, so "merchant chose no color" stays distinguishable from any real value.
1058
1133
  */
1059
- progressColor: z14.string().optional(),
1060
- sectionType: z14.literal(SectionType.progressBar).default(SectionType.progressBar),
1134
+ progressColor: z15.string().optional(),
1135
+ sectionType: z15.literal(SectionType.progressBar).default(SectionType.progressBar),
1061
1136
  /**
1062
1137
  * The bar's milestones in the merchant's CONFIGURED order — the renderer does NOT sort them (022
1063
1138
  * O-B2: sorting by resolved threshold reversed configured milestones on out-of-order or mixed-unit
1064
1139
  * count-vs-cents bars). Drives the fill (even slot per tier) and, for smart-cart product tiers, the
1065
1140
  * gift add/remove. The visual tier display lives in `sections` (composable), NOT here.
1066
1141
  */
1067
- tiers: z14.union([z14.array(CABProgressTier), z14.strictObject({}).transform(() => [])]).default(() => [])
1142
+ tiers: z15.union([z15.array(CABProgressTier), z15.strictObject({}).transform(() => [])]).default(() => [])
1068
1143
  })
1069
1144
  );
1070
1145
 
1071
1146
  // src/schema/widgets/checkout-and-beyond/quantity.ts
1072
1147
  import { v7 as uuidv79 } from "uuid";
1073
- import { z as z15 } from "zod";
1074
- var CABQuantitySection = z15.object({
1075
- errorMessages: z15.record(
1076
- z15.string(),
1077
- z15.object({
1148
+ import { z as z16 } from "zod";
1149
+ var CABQuantitySection = z16.object({
1150
+ ...CABVariableFields,
1151
+ errorMessages: z16.record(
1152
+ z16.string(),
1153
+ z16.object({
1078
1154
  /** `{{step}}` is interpolated at render — the off-increment message React never gave a merchant key. */
1079
- increment: z15.string().optional(),
1080
- max: z15.string().optional(),
1081
- min: z15.string().optional(),
1082
- neg: z15.string().optional()
1155
+ increment: z16.string().optional(),
1156
+ max: z16.string().optional(),
1157
+ min: z16.string().optional(),
1158
+ neg: z16.string().optional()
1083
1159
  })
1084
1160
  ).default({
1085
1161
  en: {
@@ -1089,19 +1165,18 @@ var CABQuantitySection = z15.object({
1089
1165
  neg: "Quantity cannot be negative"
1090
1166
  }
1091
1167
  }),
1092
- inputType: z15.enum(quantityInputs).default(QuantityInput.select),
1093
- max: z15.number().min(1).max(100).default(10),
1094
- min: z15.number().min(1).default(1),
1168
+ inputType: z16.enum(quantityInputs).default(QuantityInput.select),
1169
+ max: z16.number().min(1).max(100).default(10),
1170
+ min: z16.number().min(1).default(1),
1095
1171
  /** The a11y label for the quantity control; the merchant names it in the editor, else this default. */
1096
- name: z15.string().default("Quantity"),
1097
- rule: CABRule.optional(),
1098
- sectionId: z15.uuid().default(() => uuidv79()),
1099
- sectionType: z15.literal(SectionType.quantity).default(SectionType.quantity)
1172
+ name: z16.string().default("Quantity"),
1173
+ sectionId: z16.uuid().default(() => uuidv79()),
1174
+ sectionType: z16.literal(SectionType.quantity).default(SectionType.quantity)
1100
1175
  });
1101
1176
 
1102
1177
  // src/schema/widgets/checkout-and-beyond/reviews.ts
1103
1178
  import { v7 as uuidv710 } from "uuid";
1104
- import { z as z16 } from "zod";
1179
+ import { z as z17 } from "zod";
1105
1180
 
1106
1181
  // src/schema/widgets/checkout-and-beyond/reviewLabels.ts
1107
1182
  var REVIEW_LABELS = {
@@ -1164,50 +1239,50 @@ var REVIEW_LABELS = {
1164
1239
  };
1165
1240
 
1166
1241
  // src/schema/widgets/checkout-and-beyond/reviews.ts
1167
- var CABReviewsSection = z16.object({
1168
- color: z16.string().default("#fadb14"),
1242
+ var CABReviewsSection = z17.object({
1243
+ ...CABVariableFields,
1244
+ color: z17.string().default("#fadb14"),
1169
1245
  /**
1170
1246
  * Localized review-count templates (`{{reviewCount}}`), one/other plural forms; the client picks the
1171
1247
  * form via `Intl.PluralRules`. Defaults here (schema-first) so every tree localizes without converter
1172
1248
  * or merchant work.
1173
1249
  */
1174
- countLabels: z16.object({
1175
- one: z16.record(z16.string(), z16.string()).default(() => ({ ...REVIEW_LABELS.one })),
1176
- other: z16.record(z16.string(), z16.string()).default(() => ({ ...REVIEW_LABELS.other }))
1250
+ countLabels: z17.object({
1251
+ one: z17.record(z17.string(), z17.string()).default(() => ({ ...REVIEW_LABELS.one })),
1252
+ other: z17.record(z17.string(), z17.string()).default(() => ({ ...REVIEW_LABELS.other }))
1177
1253
  }).default(() => ({ one: { ...REVIEW_LABELS.one }, other: { ...REVIEW_LABELS.other } })),
1178
- name: z16.string().optional(),
1179
- rule: CABRule.optional(),
1180
- sectionId: z16.uuid().default(() => uuidv710()),
1181
- sectionType: z16.literal(SectionType.reviews).default(SectionType.reviews),
1182
- size: z16.enum(reviewsSizes).default(ReviewsSize.default)
1254
+ name: z17.string().optional(),
1255
+ sectionId: z17.uuid().default(() => uuidv710()),
1256
+ sectionType: z17.literal(SectionType.reviews).default(SectionType.reviews),
1257
+ size: z17.enum(reviewsSizes).default(ReviewsSize.default)
1183
1258
  });
1184
1259
 
1185
1260
  // src/schema/widgets/checkout-and-beyond/variants.ts
1186
1261
  import { slice } from "es-toolkit/compat";
1187
1262
  import { v7 as uuidv711 } from "uuid";
1188
- import { z as z17 } from "zod";
1189
- var CABVariantsSection = z17.object({
1190
- hideOutOfStockVariants: z17.boolean().default(false),
1191
- name: z17.string().optional(),
1192
- rule: CABRule.optional(),
1193
- sectionId: z17.uuid().default(() => uuidv711()),
1194
- sectionType: z17.literal(SectionType.variants).default(SectionType.variants),
1195
- selector: z17.enum(slice(variantSelectors, 0, 3)).default(VariantSelector.menu),
1196
- variantMode: z17.enum(variantModes).default(VariantMode.multiple)
1263
+ import { z as z18 } from "zod";
1264
+ var CABVariantsSection = z18.object({
1265
+ ...CABVariableFields,
1266
+ hideOutOfStockVariants: z18.boolean().default(false),
1267
+ name: z18.string().optional(),
1268
+ sectionId: z18.uuid().default(() => uuidv711()),
1269
+ sectionType: z18.literal(SectionType.variants).default(SectionType.variants),
1270
+ selector: z18.enum(slice(variantSelectors, 0, 3)).default(VariantSelector.menu),
1271
+ variantMode: z18.enum(variantModes).default(VariantMode.multiple)
1197
1272
  });
1198
1273
 
1199
1274
  // src/schema/widgets/checkout-and-beyond/shared.ts
1200
- var CABBorder = z18.object({
1201
- radius: z18.enum(borderRadii).default(BorderRadius.base),
1202
- style: z18.enum(borderStyles).default(BorderStyle.none),
1203
- width: z18.enum(borderWidths).default(BorderWidth.base)
1275
+ var CABBorder = z19.object({
1276
+ radius: z19.enum(borderRadii).default(BorderRadius.base),
1277
+ style: z19.enum(borderStyles).default(BorderStyle.none),
1278
+ width: z19.enum(borderWidths).default(BorderWidth.base)
1204
1279
  }).default({
1205
1280
  radius: BorderRadius.base,
1206
1281
  style: BorderStyle.none,
1207
1282
  width: BorderWidth.base
1208
1283
  });
1209
- var CABSection = z18.lazy(
1210
- () => z18.discriminatedUnion("sectionType", [
1284
+ var CABSection = z19.lazy(
1285
+ () => z19.discriminatedUnion("sectionType", [
1211
1286
  CABBannerSection,
1212
1287
  CABButtonSection,
1213
1288
  CABCarouselSection,
@@ -1229,16 +1304,17 @@ var CABSection = z18.lazy(
1229
1304
  );
1230
1305
 
1231
1306
  // src/schema/widgets/checkout-and-beyond/image.ts
1232
- var CABImageSectionFields = z19.object({
1233
- altText: z19.string().refine(checkForHTML, NO_HTML).default(""),
1307
+ var CABImageSectionFields = z20.object({
1308
+ ...CABVariableFields,
1309
+ altText: z20.string().refine(checkForHTML, NO_HTML).default(""),
1234
1310
  /**
1235
1311
  * Image width÷height (e.g. `46` for the progress-bar fill); `null` renders at natural size. Any POSITIVE
1236
1312
  * ratio — never limited to 1, but never `0`/negative either: a renderer dividing by it would get `Infinity`,
1237
1313
  * and CSS `aspect-ratio` drops a negative value and silently reverts to natural size.
1238
1314
  */
1239
- aspectRatio: z19.number().positive().nullable().default(null),
1240
- border: z19.lazy(() => CABBorder),
1241
- buttonField: z19.enum(buttonFields).optional(),
1315
+ aspectRatio: z20.number().positive().nullable().default(null),
1316
+ border: z20.lazy(() => CABBorder),
1317
+ buttonField: z20.enum(buttonFields).optional(),
1242
1318
  /**
1243
1319
  * `icon` renders `source` as a single `s-icon` by name (the uber-image path covers icons too), reading
1244
1320
  * `iconSize`/`iconTone`. The other values are a harmless informational holdover from the previous
@@ -1257,30 +1333,29 @@ var CABImageSectionFields = z19.object({
1257
1333
  * behavior degraded gracefully and told us about it. The client-assembled half of the invariant was never
1258
1334
  * the risky half.
1259
1335
  */
1260
- category: z19.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
1336
+ category: z20.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
1261
1337
  /** `icon`-mode only: the `s-icon` `size`; `null` ⇒ the component default (`base`). Ignored by image treatments. */
1262
- iconSize: z19.enum(iconSizes).nullable().default(null),
1338
+ iconSize: z20.enum(iconSizes).nullable().default(null),
1263
1339
  /** `icon`-mode only: the `s-icon` `tone`; `null` ⇒ the component default (`auto`). Ignored by image treatments. */
1264
- iconTone: z19.enum(iconTones).nullable().default(null),
1265
- name: z19.string().optional(),
1266
- naturalHeight: z19.number().default(0),
1267
- naturalWidth: z19.number().default(0),
1340
+ iconTone: z20.enum(iconTones).nullable().default(null),
1341
+ name: z20.string().optional(),
1342
+ naturalHeight: z20.number().default(0),
1343
+ naturalWidth: z20.number().default(0),
1268
1344
  /**
1269
1345
  * `contain` (the component default): dimensionless images render in s-image's 1/1 default frame, and
1270
1346
  * `cover` would crop non-square art (payment badges lost their edges — 15993); `contain` letterboxes.
1271
1347
  */
1272
- objectFit: z19.enum(objectFits).default(ObjectFit.contain),
1273
- rule: CABRule.optional(),
1274
- sectionId: z19.uuid().default(() => uuidv712()),
1275
- sectionType: z19.literal(SectionType.image).default(SectionType.image),
1348
+ objectFit: z20.enum(objectFits).default(ObjectFit.contain),
1349
+ sectionId: z20.uuid().default(() => uuidv712()),
1350
+ sectionType: z20.literal(SectionType.image).default(SectionType.image),
1276
1351
  /**
1277
1352
  * An image URL or dynamic token, an empty default, or — when `category: 'icon'` — an icon NAME. Icon mode
1278
1353
  * takes a name or `''` only, NOT a token: no renderer resolves a token to an icon today, so accepting one
1279
1354
  * would promise a capability that doesn't exist. Widen the refine's carve-out to `DYNAMIC_TOKEN_REGEX` when a
1280
1355
  * server-chosen tier icon actually needs it.
1281
1356
  */
1282
- source: z19.union([z19.url(), z19.literal(""), z19.string().regex(DYNAMIC_TOKEN_REGEX), z19.enum(iconNames)]).default(""),
1283
- width: z19.number().default(100)
1357
+ source: z20.union([z20.url(), z20.literal(""), z20.string().regex(DYNAMIC_TOKEN_REGEX), z20.enum(iconNames)]).default(""),
1358
+ width: z20.number().default(100)
1284
1359
  });
1285
1360
  var iconNameSet = new Set(iconNames);
1286
1361
  var isIconName = (source) => iconNameSet.has(source);
@@ -1430,7 +1505,7 @@ var convertContentBlockTextToV2 = (language) => {
1430
1505
  };
1431
1506
 
1432
1507
  // src/schema/widgets/checkout-and-beyond/root.ts
1433
- import { z as z20 } from "zod";
1508
+ import { z as z21 } from "zod";
1434
1509
 
1435
1510
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
1436
1511
  var UI_LABELS = {
@@ -1446,8 +1521,8 @@ var UI_LABELS = {
1446
1521
  };
1447
1522
 
1448
1523
  // src/schema/widgets/checkout-and-beyond/root.ts
1449
- var localized = (fallback) => z20.record(z20.string(), z20.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1450
- var CABUILabels = z20.object({
1524
+ var localized = (fallback) => z21.record(z21.string(), z21.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1525
+ var CABUILabels = z21.object({
1451
1526
  currentPage: localized(UI_LABELS.currentPage),
1452
1527
  loadingOptions: localized(UI_LABELS.loadingOptions),
1453
1528
  nextPage: localized(UI_LABELS.nextPage),
@@ -1468,37 +1543,37 @@ var CABUILabels = z20.object({
1468
1543
  subscriptionOptions: { ...UI_LABELS.subscriptionOptions },
1469
1544
  updating: { ...UI_LABELS.updating }
1470
1545
  }));
1471
- var TargetArea = z20.object({
1472
- fill: z20.boolean().optional(),
1473
- flip: z20.enum(["both", "horizontal", "vertical"]).optional(),
1474
- icon: z20.string(),
1475
- label: z20.string(),
1476
- width: z20.string()
1546
+ var TargetArea = z21.object({
1547
+ fill: z21.boolean().optional(),
1548
+ flip: z21.enum(["both", "horizontal", "vertical"]).optional(),
1549
+ icon: z21.string(),
1550
+ label: z21.string(),
1551
+ width: z21.string()
1477
1552
  }).default(targetAreas[EditorMode.checkoutExtension][1]);
1478
- var CABTracking = z20.object({
1479
- enableAttribution: z20.boolean().nullish().transform((value) => value ?? true),
1480
- enableSource: z20.boolean().nullish().transform((value) => value ?? true),
1481
- enableWidget: z20.boolean().nullish().transform((value) => value ?? true)
1553
+ var CABTracking = z21.object({
1554
+ enableAttribution: z21.boolean().nullish().transform((value) => value ?? true),
1555
+ enableSource: z21.boolean().nullish().transform((value) => value ?? true),
1556
+ enableWidget: z21.boolean().nullish().transform((value) => value ?? true)
1482
1557
  }).nullish().transform((value) => value ?? { enableAttribution: true, enableSource: true, enableWidget: true });
1483
- var CABExperiment = z20.object({
1484
- elementId: z20.number(),
1485
- experimentId: z20.number(),
1486
- experimentType: z20.string(),
1487
- selectedId: z20.number()
1558
+ var CABExperiment = z21.object({
1559
+ elementId: z21.number(),
1560
+ experimentId: z21.number(),
1561
+ experimentType: z21.string(),
1562
+ selectedId: z21.number()
1488
1563
  });
1489
1564
  var CABRootSection = CABLayoutSection.extend({
1490
- editorMode: z20.enum(editorModes).default(EditorMode.checkoutExtension),
1565
+ editorMode: z21.enum(editorModes).default(EditorMode.checkoutExtension),
1491
1566
  experiment: CABExperiment.optional(),
1492
1567
  // Same rule as CABTracking above: the v1 converters pass raw legacy `previewMode` through, so a
1493
1568
  // `null` must fall back rather than throw the widget; malformed values still throw.
1494
- previewMode: z20.boolean().nullish().transform((value) => value ?? false),
1495
- storeId: z20.number().nullable().default(null),
1569
+ previewMode: z21.boolean().nullish().transform((value) => value ?? false),
1570
+ storeId: z21.number().nullable().default(null),
1496
1571
  targetArea: TargetArea.nullable(),
1497
1572
  tracking: CABTracking,
1498
- type: z20.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
1573
+ type: z21.enum(widgetTypes).default(WidgetType.ui_extension_content_block),
1499
1574
  uiLabels: CABUILabels,
1500
- version: z20.literal(2).default(2),
1501
- widgetId: z20.number().nullable().default(null)
1575
+ version: z21.literal(2).default(2),
1576
+ widgetId: z21.number().nullable().default(null)
1502
1577
  });
1503
1578
 
1504
1579
  // src/transforms/v1Location.ts
@@ -3083,6 +3158,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
3083
3158
  sectionType: "carousel"
3084
3159
  };
3085
3160
  return CABRootSection.parse({
3161
+ alignment: { horizontal: "center", vertical: "top" },
3086
3162
  direction: "rows",
3087
3163
  editorMode: LOCATION_TO_EDITOR_MODE[settings.location ?? "checkout"],
3088
3164
  // The widget name is required by the admin save schema; carry the legacy widget's name through.