@rebuy/rebuy 3.45.0 → 3.47.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.
package/dist/index.cjs CHANGED
@@ -3704,6 +3704,13 @@ var CABButtonSection = import_zod52.z.object({
3704
3704
  width: 300
3705
3705
  }),
3706
3706
  disableDowngrade: import_zod52.z.boolean().default(false),
3707
+ /**
3708
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
3709
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
3710
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
3711
+ * (REB-24846); an unknown value reads as absent.
3712
+ */
3713
+ frequencyLabel: import_zod52.z.enum(["planName", "template"]).optional().catch(void 0),
3707
3714
  name: import_zod52.z.string().optional(),
3708
3715
  optionId: import_zod52.z.number().optional(),
3709
3716
  popover: import_zod52.z.object({
@@ -4343,6 +4350,20 @@ var import_zod65 = require("zod");
4343
4350
  var CABVariantsSection = import_zod65.z.object({
4344
4351
  ...CABVariableFields,
4345
4352
  hideOutOfStockVariants: import_zod65.z.boolean().default(false),
4353
+ /**
4354
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
4355
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
4356
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
4357
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
4358
+ *
4359
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
4360
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
4361
+ * A label left with no entries reads as absent.
4362
+ */
4363
+ label: import_zod65.z.record(import_zod65.z.string(), import_zod65.z.string()).transform((label) => {
4364
+ const filled = (0, import_compat5.pickBy)(label, (value) => value.trim() !== "");
4365
+ return (0, import_compat5.isEmpty)(filled) ? void 0 : filled;
4366
+ }).optional().catch(void 0),
4346
4367
  name: import_zod65.z.string().optional(),
4347
4368
  sectionId: import_zod65.z.uuid().default(() => (0, import_uuid14.v7)()),
4348
4369
  sectionType: import_zod65.z.literal(SectionType.variants).default(SectionType.variants),
@@ -6220,6 +6241,7 @@ var subscriptionToggle = (productType, labels = {}) => {
6220
6241
  buttonStyle: "plain",
6221
6242
  /** A `subscription` widget offers no one-time purchase; suppress the downgrade so the buyer can't switch to one-time. */
6222
6243
  ...productType === "subscription" && { disableDowngrade: true },
6244
+ ...labels.frequencyLabel && { frequencyLabel: labels.frequencyLabel },
6223
6245
  sections: [
6224
6246
  slot("subscriptionOption", void 0),
6225
6247
  slot("switchToOneTimePurchase", labels.oneTime),
package/dist/index.mjs CHANGED
@@ -3233,6 +3233,13 @@ var CABButtonSection = z52.object({
3233
3233
  width: 300
3234
3234
  }),
3235
3235
  disableDowngrade: z52.boolean().default(false),
3236
+ /**
3237
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
3238
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
3239
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
3240
+ * (REB-24846); an unknown value reads as absent.
3241
+ */
3242
+ frequencyLabel: z52.enum(["planName", "template"]).optional().catch(void 0),
3236
3243
  name: z52.string().optional(),
3237
3244
  optionId: z52.number().optional(),
3238
3245
  popover: z52.object({
@@ -3866,12 +3873,26 @@ var CABSeparatorSection = z64.object({
3866
3873
  });
3867
3874
 
3868
3875
  // src/schema/widgets/checkout-and-beyond/variants.ts
3869
- import { slice } from "es-toolkit/compat";
3876
+ import { isEmpty, pickBy, slice } from "es-toolkit/compat";
3870
3877
  import { v7 as uuidv712 } from "uuid";
3871
3878
  import { z as z65 } from "zod";
3872
3879
  var CABVariantsSection = z65.object({
3873
3880
  ...CABVariableFields,
3874
3881
  hideOutOfStockVariants: z65.boolean().default(false),
3882
+ /**
3883
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
3884
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
3885
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
3886
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
3887
+ *
3888
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
3889
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
3890
+ * A label left with no entries reads as absent.
3891
+ */
3892
+ label: z65.record(z65.string(), z65.string()).transform((label) => {
3893
+ const filled = pickBy(label, (value) => value.trim() !== "");
3894
+ return isEmpty(filled) ? void 0 : filled;
3895
+ }).optional().catch(void 0),
3875
3896
  name: z65.string().optional(),
3876
3897
  sectionId: z65.uuid().default(() => uuidv712()),
3877
3898
  sectionType: z65.literal(SectionType.variants).default(SectionType.variants),
@@ -5749,6 +5770,7 @@ var subscriptionToggle = (productType, labels = {}) => {
5749
5770
  buttonStyle: "plain",
5750
5771
  /** A `subscription` widget offers no one-time purchase; suppress the downgrade so the buyer can't switch to one-time. */
5751
5772
  ...productType === "subscription" && { disableDowngrade: true },
5773
+ ...labels.frequencyLabel && { frequencyLabel: labels.frequencyLabel },
5752
5774
  sections: [
5753
5775
  slot("subscriptionOption", void 0),
5754
5776
  slot("switchToOneTimePurchase", labels.oneTime),
@@ -926,6 +926,13 @@ var CABButtonSection = import_zod6.z.object({
926
926
  width: 300
927
927
  }),
928
928
  disableDowngrade: import_zod6.z.boolean().default(false),
929
+ /**
930
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
931
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
932
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
933
+ * (REB-24846); an unknown value reads as absent.
934
+ */
935
+ frequencyLabel: import_zod6.z.enum(["planName", "template"]).optional().catch(void 0),
929
936
  name: import_zod6.z.string().optional(),
930
937
  optionId: import_zod6.z.number().optional(),
931
938
  popover: import_zod6.z.object({
@@ -1618,6 +1625,20 @@ var import_zod19 = require("zod");
1618
1625
  var CABVariantsSection = import_zod19.z.object({
1619
1626
  ...CABVariableFields,
1620
1627
  hideOutOfStockVariants: import_zod19.z.boolean().default(false),
1628
+ /**
1629
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
1630
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
1631
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
1632
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
1633
+ *
1634
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
1635
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
1636
+ * A label left with no entries reads as absent.
1637
+ */
1638
+ label: import_zod19.z.record(import_zod19.z.string(), import_zod19.z.string()).transform((label) => {
1639
+ const filled = (0, import_compat3.pickBy)(label, (value) => value.trim() !== "");
1640
+ return (0, import_compat3.isEmpty)(filled) ? void 0 : filled;
1641
+ }).optional().catch(void 0),
1621
1642
  name: import_zod19.z.string().optional(),
1622
1643
  sectionId: import_zod19.z.uuid().default(() => (0, import_uuid12.v7)()),
1623
1644
  sectionType: import_zod19.z.literal(SectionType.variants).default(SectionType.variants),
@@ -712,6 +712,13 @@ var CABButtonSection = z6.object({
712
712
  width: 300
713
713
  }),
714
714
  disableDowngrade: z6.boolean().default(false),
715
+ /**
716
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
717
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
718
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
719
+ * (REB-24846); an unknown value reads as absent.
720
+ */
721
+ frequencyLabel: z6.enum(["planName", "template"]).optional().catch(void 0),
715
722
  name: z6.string().optional(),
716
723
  optionId: z6.number().optional(),
717
724
  popover: z6.object({
@@ -1398,12 +1405,26 @@ var CABSeparatorSection = z18.object({
1398
1405
  });
1399
1406
 
1400
1407
  // src/schema/widgets/checkout-and-beyond/variants.ts
1401
- import { slice } from "es-toolkit/compat";
1408
+ import { isEmpty, pickBy, slice } from "es-toolkit/compat";
1402
1409
  import { v7 as uuidv712 } from "uuid";
1403
1410
  import { z as z19 } from "zod";
1404
1411
  var CABVariantsSection = z19.object({
1405
1412
  ...CABVariableFields,
1406
1413
  hideOutOfStockVariants: z19.boolean().default(false),
1414
+ /**
1415
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
1416
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
1417
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
1418
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
1419
+ *
1420
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
1421
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
1422
+ * A label left with no entries reads as absent.
1423
+ */
1424
+ label: z19.record(z19.string(), z19.string()).transform((label) => {
1425
+ const filled = pickBy(label, (value) => value.trim() !== "");
1426
+ return isEmpty(filled) ? void 0 : filled;
1427
+ }).optional().catch(void 0),
1407
1428
  name: z19.string().optional(),
1408
1429
  sectionId: z19.uuid().default(() => uuidv712()),
1409
1430
  sectionType: z19.literal(SectionType.variants).default(SectionType.variants),
@@ -802,6 +802,13 @@ var CABButtonSection = import_zod9.z.object({
802
802
  width: 300
803
803
  }),
804
804
  disableDowngrade: import_zod9.z.boolean().default(false),
805
+ /**
806
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
807
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
808
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
809
+ * (REB-24846); an unknown value reads as absent.
810
+ */
811
+ frequencyLabel: import_zod9.z.enum(["planName", "template"]).optional().catch(void 0),
805
812
  name: import_zod9.z.string().optional(),
806
813
  optionId: import_zod9.z.number().optional(),
807
814
  popover: import_zod9.z.object({
@@ -1441,6 +1448,20 @@ var import_zod22 = require("zod");
1441
1448
  var CABVariantsSection = import_zod22.z.object({
1442
1449
  ...CABVariableFields,
1443
1450
  hideOutOfStockVariants: import_zod22.z.boolean().default(false),
1451
+ /**
1452
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
1453
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
1454
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
1455
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
1456
+ *
1457
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
1458
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
1459
+ * A label left with no entries reads as absent.
1460
+ */
1461
+ label: import_zod22.z.record(import_zod22.z.string(), import_zod22.z.string()).transform((label) => {
1462
+ const filled = (0, import_compat3.pickBy)(label, (value) => value.trim() !== "");
1463
+ return (0, import_compat3.isEmpty)(filled) ? void 0 : filled;
1464
+ }).optional().catch(void 0),
1444
1465
  name: import_zod22.z.string().optional(),
1445
1466
  sectionId: import_zod22.z.uuid().default(() => (0, import_uuid12.v7)()),
1446
1467
  sectionType: import_zod22.z.literal(SectionType.variants).default(SectionType.variants),
@@ -777,6 +777,13 @@ var CABButtonSection = z9.object({
777
777
  width: 300
778
778
  }),
779
779
  disableDowngrade: z9.boolean().default(false),
780
+ /**
781
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
782
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
783
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
784
+ * (REB-24846); an unknown value reads as absent.
785
+ */
786
+ frequencyLabel: z9.enum(["planName", "template"]).optional().catch(void 0),
780
787
  name: z9.string().optional(),
781
788
  optionId: z9.number().optional(),
782
789
  popover: z9.object({
@@ -1410,12 +1417,26 @@ var CABSeparatorSection = z21.object({
1410
1417
  });
1411
1418
 
1412
1419
  // src/schema/widgets/checkout-and-beyond/variants.ts
1413
- import { slice } from "es-toolkit/compat";
1420
+ import { isEmpty, pickBy, slice } from "es-toolkit/compat";
1414
1421
  import { v7 as uuidv712 } from "uuid";
1415
1422
  import { z as z22 } from "zod";
1416
1423
  var CABVariantsSection = z22.object({
1417
1424
  ...CABVariableFields,
1418
1425
  hideOutOfStockVariants: z22.boolean().default(false),
1426
+ /**
1427
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
1428
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
1429
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
1430
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
1431
+ *
1432
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
1433
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
1434
+ * A label left with no entries reads as absent.
1435
+ */
1436
+ label: z22.record(z22.string(), z22.string()).transform((label) => {
1437
+ const filled = pickBy(label, (value) => value.trim() !== "");
1438
+ return isEmpty(filled) ? void 0 : filled;
1439
+ }).optional().catch(void 0),
1419
1440
  name: z22.string().optional(),
1420
1441
  sectionId: z22.uuid().default(() => uuidv712()),
1421
1442
  sectionType: z22.literal(SectionType.variants).default(SectionType.variants),
@@ -36,6 +36,10 @@ export declare const CABButtonSection: z.ZodObject<{
36
36
  width: z.ZodDefault<z.ZodNumber>;
37
37
  }, z.core.$strip>>;
38
38
  disableDowngrade: z.ZodDefault<z.ZodBoolean>;
39
+ frequencyLabel: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
40
+ planName: "planName";
41
+ template: "template";
42
+ }>>>;
39
43
  name: z.ZodOptional<z.ZodString>;
40
44
  optionId: z.ZodOptional<z.ZodNumber>;
41
45
  popover: z.ZodDefault<z.ZodOptional<z.ZodObject<{
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
  import { type SectionDetails } from './shared';
3
3
  export declare const CABVariantsSection: z.ZodObject<{
4
4
  hideOutOfStockVariants: z.ZodDefault<z.ZodBoolean>;
5
+ label: z.ZodCatch<z.ZodOptional<z.ZodPipe<z.ZodRecord<z.ZodString, z.ZodString>, z.ZodTransform<Record<string, string> | undefined, Record<string, string>>>>>;
5
6
  name: z.ZodOptional<z.ZodString>;
6
7
  sectionId: z.ZodDefault<z.ZodUUID>;
7
8
  sectionType: z.ZodDefault<z.ZodLiteral<"variants">>;
@@ -5,7 +5,7 @@ import { type MonetizeInput } from '../server/shared';
5
5
  * Compose one ads-engine offer into a renderable CAB card: a bordered `layout` whose `viewUrl` is the
6
6
  * impression pixel, holding the header chrome, the copy (headline + HTML body, pre-converted to a
7
7
  * small-sized Tiptap doc by {@link smallText}) beside the optional image (75%/fill — the React desktop split),
8
- * the two CTAs in a 50/50 row, and the right-aligned Privacy Policy footer. `acceptOffer` links out
8
+ * the two CTAs in a 50/50 row, the paging dots, and the right-aligned Privacy Policy footer. `acceptOffer` links out
9
9
  * to the advertiser (`destinationUrl` = `click_url`, which self-tracks); `declineOffer` fires the
10
10
  * decline pixel (`trackingUrl`) and advances. Parsing through the schema fills defaults and validates
11
11
  * the shape.
@@ -1392,6 +1392,13 @@ var CABButtonSection = import_zod13.z.object({
1392
1392
  width: 300
1393
1393
  }),
1394
1394
  disableDowngrade: import_zod13.z.boolean().default(false),
1395
+ /**
1396
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
1397
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
1398
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
1399
+ * (REB-24846); an unknown value reads as absent.
1400
+ */
1401
+ frequencyLabel: import_zod13.z.enum(["planName", "template"]).optional().catch(void 0),
1395
1402
  name: import_zod13.z.string().optional(),
1396
1403
  optionId: import_zod13.z.number().optional(),
1397
1404
  popover: import_zod13.z.object({
@@ -2084,6 +2091,20 @@ var import_zod26 = require("zod");
2084
2091
  var CABVariantsSection = import_zod26.z.object({
2085
2092
  ...CABVariableFields,
2086
2093
  hideOutOfStockVariants: import_zod26.z.boolean().default(false),
2094
+ /**
2095
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
2096
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
2097
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
2098
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
2099
+ *
2100
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
2101
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
2102
+ * A label left with no entries reads as absent.
2103
+ */
2104
+ label: import_zod26.z.record(import_zod26.z.string(), import_zod26.z.string()).transform((label2) => {
2105
+ const filled = (0, import_compat3.pickBy)(label2, (value) => value.trim() !== "");
2106
+ return (0, import_compat3.isEmpty)(filled) ? void 0 : filled;
2107
+ }).optional().catch(void 0),
2087
2108
  name: import_zod26.z.string().optional(),
2088
2109
  sectionId: import_zod26.z.uuid().default(() => (0, import_uuid12.v7)()),
2089
2110
  sectionType: import_zod26.z.literal(SectionType.variants).default(SectionType.variants),
@@ -3363,6 +3384,7 @@ var subscriptionToggle = (productType, labels = {}) => {
3363
3384
  buttonStyle: "plain",
3364
3385
  /** A `subscription` widget offers no one-time purchase; suppress the downgrade so the buyer can't switch to one-time. */
3365
3386
  ...productType === "subscription" && { disableDowngrade: true },
3387
+ ...labels.frequencyLabel && { frequencyLabel: labels.frequencyLabel },
3366
3388
  sections: [
3367
3389
  slot("subscriptionOption", void 0),
3368
3390
  slot("switchToOneTimePurchase", labels.oneTime),
@@ -4287,13 +4309,16 @@ var convertPayButtonBlock = (raw, report) => {
4287
4309
  };
4288
4310
 
4289
4311
  // src/transforms/postPurchase/productCardControls.ts
4290
- var groupSelector = { sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4312
+ var SELECT_VARIANT = { en: "Select Variant" };
4313
+ var PRODUCT_GROUP = { en: "Option" };
4314
+ var groupSelector = { label: PRODUCT_GROUP, sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4291
4315
  var variantSelector = ({ productOptions }) => {
4292
4316
  if (!productOptions.showVariantSelectors) return [];
4293
4317
  const single = productOptions.variantSelectorDisplayMode === "single";
4294
4318
  return [
4295
4319
  {
4296
4320
  hideOutOfStockVariants: single || productOptions.hideOutOfStockVariants,
4321
+ ...single && { label: SELECT_VARIANT },
4297
4322
  sectionType: "variants",
4298
4323
  selector: "menu",
4299
4324
  variantMode: single ? "single" : "multiple"
@@ -4308,7 +4333,7 @@ var quantity = ({ language: language3, quantityInputs: quantityInputs2 }) => qua
4308
4333
  })
4309
4334
  ] : [];
4310
4335
  var productCardControls = (settings) => [
4311
- ...subscriptionToggle(settings.productType),
4336
+ ...subscriptionToggle(settings.productType, { frequencyLabel: "planName" }),
4312
4337
  groupSelector,
4313
4338
  ...variantSelector(settings),
4314
4339
  ...quantity(settings)
@@ -5605,6 +5630,25 @@ var disclaimerSections = (offer) => {
5605
5630
  }
5606
5631
  ];
5607
5632
  };
5633
+ var pagingDot = (buttonField, opacity) => ({
5634
+ buttonField,
5635
+ sectionType: SectionType.image,
5636
+ source: `data:image/svg+xml,${encodeURIComponent(
5637
+ `<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><circle cx="4" cy="4" r="4" fill="#808080" fill-opacity="${opacity}"/></svg>`
5638
+ )}`
5639
+ });
5640
+ var pagingDots = () => ({
5641
+ alignment: { horizontal: HorizontalAlignment.center, vertical: VerticalAlignment.top },
5642
+ sections: [
5643
+ {
5644
+ action: ButtonAction.showPagination,
5645
+ buttonStyle: ButtonStyle.plain,
5646
+ sections: [pagingDot(ButtonField.activePage, 1), pagingDot(ButtonField.inactivePage, 0.35)],
5647
+ sectionType: SectionType.button
5648
+ }
5649
+ ],
5650
+ sectionType: SectionType.layout
5651
+ });
5608
5652
  var composeOfferCard = (offer, input, storeName) => {
5609
5653
  const copy = {
5610
5654
  sections: [headlineText(offer.headline), smallText(offer.description)],
@@ -5661,6 +5705,7 @@ var composeOfferCard = (offer, input, storeName) => {
5661
5705
  sectionType: SectionType.layout
5662
5706
  },
5663
5707
  ...disclaimerSections(offer),
5708
+ pagingDots(),
5664
5709
  /**
5665
5710
  * Ad-unit Privacy Policy footer (compliance). Its own end-aligned layout packs a fit-content
5666
5711
  * paragraph right; the paragraph's own `textAlign: end` covers the full-width case — together
@@ -1320,6 +1320,13 @@ var CABButtonSection = z13.object({
1320
1320
  width: 300
1321
1321
  }),
1322
1322
  disableDowngrade: z13.boolean().default(false),
1323
+ /**
1324
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
1325
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
1326
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
1327
+ * (REB-24846); an unknown value reads as absent.
1328
+ */
1329
+ frequencyLabel: z13.enum(["planName", "template"]).optional().catch(void 0),
1323
1330
  name: z13.string().optional(),
1324
1331
  optionId: z13.number().optional(),
1325
1332
  popover: z13.object({
@@ -2006,12 +2013,26 @@ var CABSeparatorSection = z25.object({
2006
2013
  });
2007
2014
 
2008
2015
  // src/schema/widgets/checkout-and-beyond/variants.ts
2009
- import { slice } from "es-toolkit/compat";
2016
+ import { isEmpty, pickBy, slice } from "es-toolkit/compat";
2010
2017
  import { v7 as uuidv712 } from "uuid";
2011
2018
  import { z as z26 } from "zod";
2012
2019
  var CABVariantsSection = z26.object({
2013
2020
  ...CABVariableFields,
2014
2021
  hideOutOfStockVariants: z26.boolean().default(false),
2022
+ /**
2023
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
2024
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
2025
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
2026
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
2027
+ *
2028
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
2029
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
2030
+ * A label left with no entries reads as absent.
2031
+ */
2032
+ label: z26.record(z26.string(), z26.string()).transform((label2) => {
2033
+ const filled = pickBy(label2, (value) => value.trim() !== "");
2034
+ return isEmpty(filled) ? void 0 : filled;
2035
+ }).optional().catch(void 0),
2015
2036
  name: z26.string().optional(),
2016
2037
  sectionId: z26.uuid().default(() => uuidv712()),
2017
2038
  sectionType: z26.literal(SectionType.variants).default(SectionType.variants),
@@ -3291,6 +3312,7 @@ var subscriptionToggle = (productType, labels = {}) => {
3291
3312
  buttonStyle: "plain",
3292
3313
  /** A `subscription` widget offers no one-time purchase; suppress the downgrade so the buyer can't switch to one-time. */
3293
3314
  ...productType === "subscription" && { disableDowngrade: true },
3315
+ ...labels.frequencyLabel && { frequencyLabel: labels.frequencyLabel },
3294
3316
  sections: [
3295
3317
  slot("subscriptionOption", void 0),
3296
3318
  slot("switchToOneTimePurchase", labels.oneTime),
@@ -4215,13 +4237,16 @@ var convertPayButtonBlock = (raw, report) => {
4215
4237
  };
4216
4238
 
4217
4239
  // src/transforms/postPurchase/productCardControls.ts
4218
- var groupSelector = { sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4240
+ var SELECT_VARIANT = { en: "Select Variant" };
4241
+ var PRODUCT_GROUP = { en: "Option" };
4242
+ var groupSelector = { label: PRODUCT_GROUP, sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4219
4243
  var variantSelector = ({ productOptions }) => {
4220
4244
  if (!productOptions.showVariantSelectors) return [];
4221
4245
  const single = productOptions.variantSelectorDisplayMode === "single";
4222
4246
  return [
4223
4247
  {
4224
4248
  hideOutOfStockVariants: single || productOptions.hideOutOfStockVariants,
4249
+ ...single && { label: SELECT_VARIANT },
4225
4250
  sectionType: "variants",
4226
4251
  selector: "menu",
4227
4252
  variantMode: single ? "single" : "multiple"
@@ -4236,7 +4261,7 @@ var quantity = ({ language: language3, quantityInputs: quantityInputs2 }) => qua
4236
4261
  })
4237
4262
  ] : [];
4238
4263
  var productCardControls = (settings) => [
4239
- ...subscriptionToggle(settings.productType),
4264
+ ...subscriptionToggle(settings.productType, { frequencyLabel: "planName" }),
4240
4265
  groupSelector,
4241
4266
  ...variantSelector(settings),
4242
4267
  ...quantity(settings)
@@ -5533,6 +5558,25 @@ var disclaimerSections = (offer) => {
5533
5558
  }
5534
5559
  ];
5535
5560
  };
5561
+ var pagingDot = (buttonField, opacity) => ({
5562
+ buttonField,
5563
+ sectionType: SectionType.image,
5564
+ source: `data:image/svg+xml,${encodeURIComponent(
5565
+ `<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><circle cx="4" cy="4" r="4" fill="#808080" fill-opacity="${opacity}"/></svg>`
5566
+ )}`
5567
+ });
5568
+ var pagingDots = () => ({
5569
+ alignment: { horizontal: HorizontalAlignment.center, vertical: VerticalAlignment.top },
5570
+ sections: [
5571
+ {
5572
+ action: ButtonAction.showPagination,
5573
+ buttonStyle: ButtonStyle.plain,
5574
+ sections: [pagingDot(ButtonField.activePage, 1), pagingDot(ButtonField.inactivePage, 0.35)],
5575
+ sectionType: SectionType.button
5576
+ }
5577
+ ],
5578
+ sectionType: SectionType.layout
5579
+ });
5536
5580
  var composeOfferCard = (offer, input, storeName) => {
5537
5581
  const copy = {
5538
5582
  sections: [headlineText(offer.headline), smallText(offer.description)],
@@ -5589,6 +5633,7 @@ var composeOfferCard = (offer, input, storeName) => {
5589
5633
  sectionType: SectionType.layout
5590
5634
  },
5591
5635
  ...disclaimerSections(offer),
5636
+ pagingDots(),
5592
5637
  /**
5593
5638
  * Ad-unit Privacy Policy footer (compliance). Its own end-aligned layout packs a fit-content
5594
5639
  * paragraph right; the paragraph's own `textAlign: end` covers the full-width case — together
@@ -757,6 +757,13 @@ var CABButtonSection = import_zod7.z.object({
757
757
  width: 300
758
758
  }),
759
759
  disableDowngrade: import_zod7.z.boolean().default(false),
760
+ /**
761
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
762
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
763
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
764
+ * (REB-24846); an unknown value reads as absent.
765
+ */
766
+ frequencyLabel: import_zod7.z.enum(["planName", "template"]).optional().catch(void 0),
760
767
  name: import_zod7.z.string().optional(),
761
768
  optionId: import_zod7.z.number().optional(),
762
769
  popover: import_zod7.z.object({
@@ -1449,6 +1456,20 @@ var import_zod20 = require("zod");
1449
1456
  var CABVariantsSection = import_zod20.z.object({
1450
1457
  ...CABVariableFields,
1451
1458
  hideOutOfStockVariants: import_zod20.z.boolean().default(false),
1459
+ /**
1460
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
1461
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
1462
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
1463
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
1464
+ *
1465
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
1466
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
1467
+ * A label left with no entries reads as absent.
1468
+ */
1469
+ label: import_zod20.z.record(import_zod20.z.string(), import_zod20.z.string()).transform((label) => {
1470
+ const filled = (0, import_compat3.pickBy)(label, (value) => value.trim() !== "");
1471
+ return (0, import_compat3.isEmpty)(filled) ? void 0 : filled;
1472
+ }).optional().catch(void 0),
1452
1473
  name: import_zod20.z.string().optional(),
1453
1474
  sectionId: import_zod20.z.uuid().default(() => (0, import_uuid12.v7)()),
1454
1475
  sectionType: import_zod20.z.literal(SectionType.variants).default(SectionType.variants),
@@ -3159,6 +3180,7 @@ var subscriptionToggle = (productType, labels = {}) => {
3159
3180
  buttonStyle: "plain",
3160
3181
  /** A `subscription` widget offers no one-time purchase; suppress the downgrade so the buyer can't switch to one-time. */
3161
3182
  ...productType === "subscription" && { disableDowngrade: true },
3183
+ ...labels.frequencyLabel && { frequencyLabel: labels.frequencyLabel },
3162
3184
  sections: [
3163
3185
  slot("subscriptionOption", void 0),
3164
3186
  slot("switchToOneTimePurchase", labels.oneTime),
@@ -4091,13 +4113,16 @@ var convertPayButtonBlock = (raw, report) => {
4091
4113
  };
4092
4114
 
4093
4115
  // src/transforms/postPurchase/productCardControls.ts
4094
- var groupSelector = { sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4116
+ var SELECT_VARIANT = { en: "Select Variant" };
4117
+ var PRODUCT_GROUP = { en: "Option" };
4118
+ var groupSelector = { label: PRODUCT_GROUP, sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4095
4119
  var variantSelector = ({ productOptions }) => {
4096
4120
  if (!productOptions.showVariantSelectors) return [];
4097
4121
  const single = productOptions.variantSelectorDisplayMode === "single";
4098
4122
  return [
4099
4123
  {
4100
4124
  hideOutOfStockVariants: single || productOptions.hideOutOfStockVariants,
4125
+ ...single && { label: SELECT_VARIANT },
4101
4126
  sectionType: "variants",
4102
4127
  selector: "menu",
4103
4128
  variantMode: single ? "single" : "multiple"
@@ -4112,7 +4137,7 @@ var quantity = ({ language, quantityInputs: quantityInputs2 }) => quantityInputs
4112
4137
  })
4113
4138
  ] : [];
4114
4139
  var productCardControls = (settings) => [
4115
- ...subscriptionToggle(settings.productType),
4140
+ ...subscriptionToggle(settings.productType, { frequencyLabel: "planName" }),
4116
4141
  groupSelector,
4117
4142
  ...variantSelector(settings),
4118
4143
  ...quantity(settings)
@@ -696,6 +696,13 @@ var CABButtonSection = z7.object({
696
696
  width: 300
697
697
  }),
698
698
  disableDowngrade: z7.boolean().default(false),
699
+ /**
700
+ * What labels a `switchToSubscription` button's frequency options. `planName` shows the selling plan's
701
+ * own name (legacy post-purchase, L115) and falls back to the `subscriptionOption` template for a plan
702
+ * without one; absent or `template` is the template alone (the checkout card). Optional and additive
703
+ * (REB-24846); an unknown value reads as absent.
704
+ */
705
+ frequencyLabel: z7.enum(["planName", "template"]).optional().catch(void 0),
699
706
  name: z7.string().optional(),
700
707
  optionId: z7.number().optional(),
701
708
  popover: z7.object({
@@ -1382,12 +1389,26 @@ var CABSeparatorSection = z19.object({
1382
1389
  });
1383
1390
 
1384
1391
  // src/schema/widgets/checkout-and-beyond/variants.ts
1385
- import { slice } from "es-toolkit/compat";
1392
+ import { isEmpty, pickBy, slice } from "es-toolkit/compat";
1386
1393
  import { v7 as uuidv712 } from "uuid";
1387
1394
  import { z as z20 } from "zod";
1388
1395
  var CABVariantsSection = z20.object({
1389
1396
  ...CABVariableFields,
1390
1397
  hideOutOfStockVariants: z20.boolean().default(false),
1398
+ /**
1399
+ * The menu's own label per buyer locale (`selectLanguage`), for the whole-variant (`single`) and the
1400
+ * product-group menus; `multiple` labels each option's menu by its name. Optional and additive
1401
+ * (REB-24846): absent, a renderer keeps its own label; the post-purchase converter sets legacy's
1402
+ * "Select Variant" and "Option" (L93, L97). A malformed label drops only itself.
1403
+ *
1404
+ * A blank (or whitespace-only) entry is dropped per locale, so that buyer falls back to `en` instead of
1405
+ * `selectLanguage` returning `''` — which a renderer's `??` fallback would show as an empty menu label.
1406
+ * A label left with no entries reads as absent.
1407
+ */
1408
+ label: z20.record(z20.string(), z20.string()).transform((label) => {
1409
+ const filled = pickBy(label, (value) => value.trim() !== "");
1410
+ return isEmpty(filled) ? void 0 : filled;
1411
+ }).optional().catch(void 0),
1391
1412
  name: z20.string().optional(),
1392
1413
  sectionId: z20.uuid().default(() => uuidv712()),
1393
1414
  sectionType: z20.literal(SectionType.variants).default(SectionType.variants),
@@ -3098,6 +3119,7 @@ var subscriptionToggle = (productType, labels = {}) => {
3098
3119
  buttonStyle: "plain",
3099
3120
  /** A `subscription` widget offers no one-time purchase; suppress the downgrade so the buyer can't switch to one-time. */
3100
3121
  ...productType === "subscription" && { disableDowngrade: true },
3122
+ ...labels.frequencyLabel && { frequencyLabel: labels.frequencyLabel },
3101
3123
  sections: [
3102
3124
  slot("subscriptionOption", void 0),
3103
3125
  slot("switchToOneTimePurchase", labels.oneTime),
@@ -4030,13 +4052,16 @@ var convertPayButtonBlock = (raw, report) => {
4030
4052
  };
4031
4053
 
4032
4054
  // src/transforms/postPurchase/productCardControls.ts
4033
- var groupSelector = { sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4055
+ var SELECT_VARIANT = { en: "Select Variant" };
4056
+ var PRODUCT_GROUP = { en: "Option" };
4057
+ var groupSelector = { label: PRODUCT_GROUP, sectionType: "variants", selector: "menu", variantMode: "productGroup" };
4034
4058
  var variantSelector = ({ productOptions }) => {
4035
4059
  if (!productOptions.showVariantSelectors) return [];
4036
4060
  const single = productOptions.variantSelectorDisplayMode === "single";
4037
4061
  return [
4038
4062
  {
4039
4063
  hideOutOfStockVariants: single || productOptions.hideOutOfStockVariants,
4064
+ ...single && { label: SELECT_VARIANT },
4040
4065
  sectionType: "variants",
4041
4066
  selector: "menu",
4042
4067
  variantMode: single ? "single" : "multiple"
@@ -4051,7 +4076,7 @@ var quantity = ({ language, quantityInputs: quantityInputs2 }) => quantityInputs
4051
4076
  })
4052
4077
  ] : [];
4053
4078
  var productCardControls = (settings) => [
4054
- ...subscriptionToggle(settings.productType),
4079
+ ...subscriptionToggle(settings.productType, { frequencyLabel: "planName" }),
4055
4080
  groupSelector,
4056
4081
  ...variantSelector(settings),
4057
4082
  ...quantity(settings)
@@ -1,7 +1,7 @@
1
1
  import { type ProductCardSettings } from '../../transforms/postPurchase/productCardSettings';
2
2
  /**
3
3
  * The card's controls in legacy `ProductOffer` order: purchase mode, product group, variants, quantity.
4
- * The purchase mode is the checkout card's `switchToSubscription` button as-is (its default labels, and
5
- * `disableDowngrade` for a subscription-only widget).
4
+ * The purchase mode is the checkout card's `switchToSubscription` button (its default labels, and
5
+ * `disableDowngrade` for a subscription-only widget), its frequencies labelled by plan name (L115).
6
6
  */
7
7
  export declare const productCardControls: (settings: ProductCardSettings) => Record<string, unknown>[];
@@ -1,4 +1,7 @@
1
+ import { type CABButtonSection } from '../../schema/widgets/checkout-and-beyond/button';
1
2
  export type SubscriptionToggleLabels = {
3
+ /** What labels the frequency options; only the post-purchase card sets it (`planName`, L115). */
4
+ frequencyLabel?: CABButtonSection['frequencyLabel'];
2
5
  /** The switch-to-one-time label override. */
3
6
  oneTime?: string;
4
7
  /** The ONE upsell label legacy had; it fills both upsell slots. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebuy/rebuy",
3
- "version": "3.45.0",
3
+ "version": "3.47.0",
4
4
  "description": "Shared zod schemas, legacy-to-CAB widget transforms, and server orchestrators for Rebuy's Shopify consumers (rebuy-api, admin-nextjs, rebuy-shopify-extensions)",
5
5
  "license": "MIT",
6
6
  "author": "Rebuy, Inc.",