@rebuy/rebuy 3.11.0 → 3.12.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
@@ -1058,6 +1058,20 @@ var SmartCartTier = import_zod.z.looseObject({
1058
1058
  productAmountRemainingLabel: import_zod.z.boolean().optional(),
1059
1059
  productAmountRemainingLabelText: import_zod.z.string().optional(),
1060
1060
  products: import_zod.z.array(SmartCartTierProduct).optional(),
1061
+ /**
1062
+ * onsite `product_tier_element_size`: the step-row icon's square size as a px STRING (`'18px'` …
1063
+ * `'36px'` — the admin's five-value Size control, default `'18px'`). React stamps it onto the icon
1064
+ * SVG's `width`/`height` (`getProgressStepIconSize`), so the milestone renders at the merchant's
1065
+ * chosen size; the converter turns it into `CABProgressTier.iconSizePx` for the CAB renderer.
1066
+ *
1067
+ * `.catch(undefined)` for the same blast-radius reason as `productTierImage` below: this key was
1068
+ * previously unknown-and-ignored by the `looseObject`, and `SmartCartConfig` is parsed
1069
+ * `.nullish().catch(undefined)` with no intermediate catch, so one drifted value (a bare number, a
1070
+ * `'2rem'`) would drop EVERY progress bar for the shop rather than just this setting. Failing open to
1071
+ * `undefined` lands on the documented 18px default — strictly safer than that blast radius. The
1072
+ * converter parses the number out and clamps it, so a junk-but-string value degrades the same way.
1073
+ */
1074
+ productTierElementSize: import_zod.z.string().optional().catch(void 0),
1061
1075
  /**
1062
1076
  * onsite `product_tier_image`: on a product (gift) tier, show the gift's product image in the step-row
1063
1077
  * slot instead of the generic bag icon (React `TierProgressIcon` swaps in the image when this is set and
@@ -2703,6 +2717,25 @@ var CABProgressTier = import_zod24.z.object({
2703
2717
  title: import_zod24.z.string().optional(),
2704
2718
  variantIds: import_zod24.z.array(import_zod24.z.number().int().positive()).default(() => [])
2705
2719
  }).optional(),
2720
+ /**
2721
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
2722
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
2723
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
2724
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
2725
+ *
2726
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
2727
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
2728
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
2729
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
2730
+ *
2731
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
2732
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
2733
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
2734
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
2735
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
2736
+ * React's size rather than the old hardcoded 20.
2737
+ */
2738
+ iconSizePx: import_zod24.z.number().int().min(1).max(64).default(18),
2706
2739
  /**
2707
2740
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
2708
2741
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
package/dist/index.mjs CHANGED
@@ -772,6 +772,20 @@ var SmartCartTier = z.looseObject({
772
772
  productAmountRemainingLabel: z.boolean().optional(),
773
773
  productAmountRemainingLabelText: z.string().optional(),
774
774
  products: z.array(SmartCartTierProduct).optional(),
775
+ /**
776
+ * onsite `product_tier_element_size`: the step-row icon's square size as a px STRING (`'18px'` …
777
+ * `'36px'` — the admin's five-value Size control, default `'18px'`). React stamps it onto the icon
778
+ * SVG's `width`/`height` (`getProgressStepIconSize`), so the milestone renders at the merchant's
779
+ * chosen size; the converter turns it into `CABProgressTier.iconSizePx` for the CAB renderer.
780
+ *
781
+ * `.catch(undefined)` for the same blast-radius reason as `productTierImage` below: this key was
782
+ * previously unknown-and-ignored by the `looseObject`, and `SmartCartConfig` is parsed
783
+ * `.nullish().catch(undefined)` with no intermediate catch, so one drifted value (a bare number, a
784
+ * `'2rem'`) would drop EVERY progress bar for the shop rather than just this setting. Failing open to
785
+ * `undefined` lands on the documented 18px default — strictly safer than that blast radius. The
786
+ * converter parses the number out and clamps it, so a junk-but-string value degrades the same way.
787
+ */
788
+ productTierElementSize: z.string().optional().catch(void 0),
775
789
  /**
776
790
  * onsite `product_tier_image`: on a product (gift) tier, show the gift's product image in the step-row
777
791
  * slot instead of the generic bag icon (React `TierProgressIcon` swaps in the image when this is set and
@@ -2417,6 +2431,25 @@ var CABProgressTier = z24.object({
2417
2431
  title: z24.string().optional(),
2418
2432
  variantIds: z24.array(z24.number().int().positive()).default(() => [])
2419
2433
  }).optional(),
2434
+ /**
2435
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
2436
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
2437
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
2438
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
2439
+ *
2440
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
2441
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
2442
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
2443
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
2444
+ *
2445
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
2446
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
2447
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
2448
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
2449
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
2450
+ * React's size rather than the old hardcoded 20.
2451
+ */
2452
+ iconSizePx: z24.number().int().min(1).max(64).default(18),
2420
2453
  /**
2421
2454
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
2422
2455
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -144,6 +144,7 @@ export declare const CabUserConfig: z.ZodObject<{
144
144
  title: z.ZodOptional<z.ZodString>;
145
145
  variantIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
146
146
  }, z.core.$loose>>>;
147
+ productTierElementSize: z.ZodCatch<z.ZodOptional<z.ZodString>>;
147
148
  productTierImage: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
148
149
  type: z.ZodOptional<z.ZodString>;
149
150
  unlockConditionType: z.ZodOptional<z.ZodString>;
@@ -1272,6 +1272,25 @@ var CABProgressTier = import_zod14.z.object({
1272
1272
  title: import_zod14.z.string().optional(),
1273
1273
  variantIds: import_zod14.z.array(import_zod14.z.number().int().positive()).default(() => [])
1274
1274
  }).optional(),
1275
+ /**
1276
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1277
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1278
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1279
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1280
+ *
1281
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1282
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1283
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1284
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1285
+ *
1286
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1287
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1288
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1289
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1290
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1291
+ * React's size rather than the old hardcoded 20.
1292
+ */
1293
+ iconSizePx: import_zod14.z.number().int().min(1).max(64).default(18),
1275
1294
  /**
1276
1295
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1277
1296
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -1075,6 +1075,25 @@ var CABProgressTier = z14.object({
1075
1075
  title: z14.string().optional(),
1076
1076
  variantIds: z14.array(z14.number().int().positive()).default(() => [])
1077
1077
  }).optional(),
1078
+ /**
1079
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1080
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1081
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1082
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1083
+ *
1084
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1085
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1086
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1087
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1088
+ *
1089
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1090
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1091
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1092
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1093
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1094
+ * React's size rather than the old hardcoded 20.
1095
+ */
1096
+ iconSizePx: z14.number().int().min(1).max(64).default(18),
1078
1097
  /**
1079
1098
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1080
1099
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -59,6 +59,7 @@ export declare const SmartCartTier: z.ZodObject<{
59
59
  title: z.ZodOptional<z.ZodString>;
60
60
  variantIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
61
61
  }, z.core.$loose>>>;
62
+ productTierElementSize: z.ZodCatch<z.ZodOptional<z.ZodString>>;
62
63
  productTierImage: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
63
64
  type: z.ZodOptional<z.ZodString>;
64
65
  unlockConditionType: z.ZodOptional<z.ZodString>;
@@ -120,6 +121,7 @@ export declare const SmartCartBar: z.ZodObject<{
120
121
  title: z.ZodOptional<z.ZodString>;
121
122
  variantIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
122
123
  }, z.core.$loose>>>;
124
+ productTierElementSize: z.ZodCatch<z.ZodOptional<z.ZodString>>;
123
125
  productTierImage: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
124
126
  type: z.ZodOptional<z.ZodString>;
125
127
  unlockConditionType: z.ZodOptional<z.ZodString>;
@@ -180,6 +182,7 @@ export declare const SmartCartComponent: z.ZodObject<{
180
182
  title: z.ZodOptional<z.ZodString>;
181
183
  variantIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
182
184
  }, z.core.$loose>>>;
185
+ productTierElementSize: z.ZodCatch<z.ZodOptional<z.ZodString>>;
183
186
  productTierImage: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
184
187
  type: z.ZodOptional<z.ZodString>;
185
188
  unlockConditionType: z.ZodOptional<z.ZodString>;
@@ -251,6 +254,7 @@ export declare const SmartCartConfig: z.ZodObject<{
251
254
  title: z.ZodOptional<z.ZodString>;
252
255
  variantIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
253
256
  }, z.core.$loose>>>;
257
+ productTierElementSize: z.ZodCatch<z.ZodOptional<z.ZodString>>;
254
258
  productTierImage: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
255
259
  type: z.ZodOptional<z.ZodString>;
256
260
  unlockConditionType: z.ZodOptional<z.ZodString>;
@@ -151,6 +151,20 @@ var SmartCartTier = import_zod2.z.looseObject({
151
151
  productAmountRemainingLabel: import_zod2.z.boolean().optional(),
152
152
  productAmountRemainingLabelText: import_zod2.z.string().optional(),
153
153
  products: import_zod2.z.array(SmartCartTierProduct).optional(),
154
+ /**
155
+ * onsite `product_tier_element_size`: the step-row icon's square size as a px STRING (`'18px'` …
156
+ * `'36px'` — the admin's five-value Size control, default `'18px'`). React stamps it onto the icon
157
+ * SVG's `width`/`height` (`getProgressStepIconSize`), so the milestone renders at the merchant's
158
+ * chosen size; the converter turns it into `CABProgressTier.iconSizePx` for the CAB renderer.
159
+ *
160
+ * `.catch(undefined)` for the same blast-radius reason as `productTierImage` below: this key was
161
+ * previously unknown-and-ignored by the `looseObject`, and `SmartCartConfig` is parsed
162
+ * `.nullish().catch(undefined)` with no intermediate catch, so one drifted value (a bare number, a
163
+ * `'2rem'`) would drop EVERY progress bar for the shop rather than just this setting. Failing open to
164
+ * `undefined` lands on the documented 18px default — strictly safer than that blast radius. The
165
+ * converter parses the number out and clamps it, so a junk-but-string value degrades the same way.
166
+ */
167
+ productTierElementSize: import_zod2.z.string().optional().catch(void 0),
154
168
  /**
155
169
  * onsite `product_tier_image`: on a product (gift) tier, show the gift's product image in the step-row
156
170
  * slot instead of the generic bag icon (React `TierProgressIcon` swaps in the image when this is set and
@@ -127,6 +127,20 @@ var SmartCartTier = z2.looseObject({
127
127
  productAmountRemainingLabel: z2.boolean().optional(),
128
128
  productAmountRemainingLabelText: z2.string().optional(),
129
129
  products: z2.array(SmartCartTierProduct).optional(),
130
+ /**
131
+ * onsite `product_tier_element_size`: the step-row icon's square size as a px STRING (`'18px'` …
132
+ * `'36px'` — the admin's five-value Size control, default `'18px'`). React stamps it onto the icon
133
+ * SVG's `width`/`height` (`getProgressStepIconSize`), so the milestone renders at the merchant's
134
+ * chosen size; the converter turns it into `CABProgressTier.iconSizePx` for the CAB renderer.
135
+ *
136
+ * `.catch(undefined)` for the same blast-radius reason as `productTierImage` below: this key was
137
+ * previously unknown-and-ignored by the `looseObject`, and `SmartCartConfig` is parsed
138
+ * `.nullish().catch(undefined)` with no intermediate catch, so one drifted value (a bare number, a
139
+ * `'2rem'`) would drop EVERY progress bar for the shop rather than just this setting. Failing open to
140
+ * `undefined` lands on the documented 18px default — strictly safer than that blast radius. The
141
+ * converter parses the number out and clamps it, so a junk-but-string value degrades the same way.
142
+ */
143
+ productTierElementSize: z2.string().optional().catch(void 0),
130
144
  /**
131
145
  * onsite `product_tier_image`: on a product (gift) tier, show the gift's product image in the step-row
132
146
  * slot instead of the generic bag icon (React `TierProgressIcon` swaps in the image when this is set and
@@ -133,6 +133,7 @@ export declare const UserConfig: z.ZodObject<{
133
133
  title: z.ZodOptional<z.ZodString>;
134
134
  variantIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
135
135
  }, z.core.$loose>>>;
136
+ productTierElementSize: z.ZodCatch<z.ZodOptional<z.ZodString>>;
136
137
  productTierImage: z.ZodCatch<z.ZodOptional<z.ZodBoolean>>;
137
138
  type: z.ZodOptional<z.ZodString>;
138
139
  unlockConditionType: z.ZodOptional<z.ZodString>;
@@ -1113,6 +1113,25 @@ var CABProgressTier = import_zod17.z.object({
1113
1113
  title: import_zod17.z.string().optional(),
1114
1114
  variantIds: import_zod17.z.array(import_zod17.z.number().int().positive()).default(() => [])
1115
1115
  }).optional(),
1116
+ /**
1117
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1118
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1119
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1120
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1121
+ *
1122
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1123
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1124
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1125
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1126
+ *
1127
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1128
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1129
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1130
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1131
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1132
+ * React's size rather than the old hardcoded 20.
1133
+ */
1134
+ iconSizePx: import_zod17.z.number().int().min(1).max(64).default(18),
1116
1135
  /**
1117
1136
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1118
1137
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -1088,6 +1088,25 @@ var CABProgressTier = z17.object({
1088
1088
  title: z17.string().optional(),
1089
1089
  variantIds: z17.array(z17.number().int().positive()).default(() => [])
1090
1090
  }).optional(),
1091
+ /**
1092
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1093
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1094
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1095
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1096
+ *
1097
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1098
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1099
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1100
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1101
+ *
1102
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1103
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1104
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1105
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1106
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1107
+ * React's size rather than the old hardcoded 20.
1108
+ */
1109
+ iconSizePx: z17.number().int().min(1).max(64).default(18),
1091
1110
  /**
1092
1111
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1093
1112
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -15,6 +15,7 @@ export declare const CABProgressTier: z.ZodObject<{
15
15
  title: z.ZodOptional<z.ZodString>;
16
16
  variantIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
17
17
  }, z.core.$strip>>;
18
+ iconSizePx: z.ZodDefault<z.ZodNumber>;
18
19
  label: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
19
20
  productTierImage: z.ZodDefault<z.ZodBoolean>;
20
21
  threshold: z.ZodNumber;
@@ -334,6 +335,7 @@ export declare const CABProgressBarSection: z.ZodLazy<z.ZodObject<{
334
335
  title: z.ZodOptional<z.ZodString>;
335
336
  variantIds: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
336
337
  }, z.core.$strip>>;
338
+ iconSizePx: z.ZodDefault<z.ZodNumber>;
337
339
  label: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
338
340
  productTierImage: z.ZodDefault<z.ZodBoolean>;
339
341
  threshold: z.ZodNumber;
@@ -478,6 +478,20 @@ var SmartCartTier = import_zod5.z.looseObject({
478
478
  productAmountRemainingLabel: import_zod5.z.boolean().optional(),
479
479
  productAmountRemainingLabelText: import_zod5.z.string().optional(),
480
480
  products: import_zod5.z.array(SmartCartTierProduct).optional(),
481
+ /**
482
+ * onsite `product_tier_element_size`: the step-row icon's square size as a px STRING (`'18px'` …
483
+ * `'36px'` — the admin's five-value Size control, default `'18px'`). React stamps it onto the icon
484
+ * SVG's `width`/`height` (`getProgressStepIconSize`), so the milestone renders at the merchant's
485
+ * chosen size; the converter turns it into `CABProgressTier.iconSizePx` for the CAB renderer.
486
+ *
487
+ * `.catch(undefined)` for the same blast-radius reason as `productTierImage` below: this key was
488
+ * previously unknown-and-ignored by the `looseObject`, and `SmartCartConfig` is parsed
489
+ * `.nullish().catch(undefined)` with no intermediate catch, so one drifted value (a bare number, a
490
+ * `'2rem'`) would drop EVERY progress bar for the shop rather than just this setting. Failing open to
491
+ * `undefined` lands on the documented 18px default — strictly safer than that blast radius. The
492
+ * converter parses the number out and clamps it, so a junk-but-string value degrades the same way.
493
+ */
494
+ productTierElementSize: import_zod5.z.string().optional().catch(void 0),
481
495
  /**
482
496
  * onsite `product_tier_image`: on a product (gift) tier, show the gift's product image in the step-row
483
497
  * slot instead of the generic bag icon (React `TierProgressIcon` swaps in the image when this is set and
@@ -1657,6 +1671,25 @@ var CABProgressTier = import_zod21.z.object({
1657
1671
  title: import_zod21.z.string().optional(),
1658
1672
  variantIds: import_zod21.z.array(import_zod21.z.number().int().positive()).default(() => [])
1659
1673
  }).optional(),
1674
+ /**
1675
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1676
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1677
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1678
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1679
+ *
1680
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1681
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1682
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1683
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1684
+ *
1685
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1686
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1687
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1688
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1689
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1690
+ * React's size rather than the old hardcoded 20.
1691
+ */
1692
+ iconSizePx: import_zod21.z.number().int().min(1).max(64).default(18),
1660
1693
  /**
1661
1694
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1662
1695
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -3530,6 +3563,7 @@ var feedbackDoc = (raw, tokens) => ({
3530
3563
  ],
3531
3564
  type: "doc"
3532
3565
  });
3566
+ var MAX_ICON_SIZE_PX = 64;
3533
3567
  var IN_SCOPE_TIER_TYPES = new Set(progressTierTypes);
3534
3568
  var inScope = (tier) => IN_SCOPE_TIER_TYPES.has(tier.type ?? "");
3535
3569
  var thresholdOf = (tier) => tier.unlockConditionType === "item_quantity" ? Math.ceil(Number(tier.minimum)) : Math.round(Number(tier.minimum) * 100);
@@ -3548,6 +3582,10 @@ var discountOf = (tier) => {
3548
3582
  const amount = tier.discountAmountFromTotal ?? 0;
3549
3583
  return tier.discountType === "fixedAmount" ? { amount: Math.round(amount * 100), type: "fixedAmount" } : { amount, type: "percentage" };
3550
3584
  };
3585
+ var iconSizeOf = (tier) => {
3586
+ const px = Math.round(Number.parseFloat(String(tier.productTierElementSize ?? "")));
3587
+ return Number.isFinite(px) && px > 0 ? Math.min(px, MAX_ICON_SIZE_PX) : void 0;
3588
+ };
3551
3589
  var giftOf = (tier) => {
3552
3590
  if (tier.type !== "product") return void 0;
3553
3591
  const product = tier.products?.[0] ?? tier.allProducts?.[0];
@@ -3564,6 +3602,7 @@ var giftOf = (tier) => {
3564
3602
  var toTierMeta = (tier) => {
3565
3603
  const discount = discountOf(tier);
3566
3604
  const gift = giftOf(tier);
3605
+ const iconSizePx = iconSizeOf(tier);
3567
3606
  const isItemCount = tier.unlockConditionType === "item_quantity";
3568
3607
  const label2 = tierLabel(tier);
3569
3608
  const type = tier.type;
@@ -3572,6 +3611,8 @@ var toTierMeta = (tier) => {
3572
3611
  /** Carry the OOS-filter flag only on gift tiers that set it — the client drops the tier when its gift is fully out of stock. */
3573
3612
  ...gift && tier.filterOosVariants && { filterOosVariants: true },
3574
3613
  ...gift && { gift },
3614
+ /** Carry the merchant's milestone icon size only when set — absent ⇒ the schema's 18px (React) default. */
3615
+ ...iconSizePx !== void 0 && { iconSizePx },
3575
3616
  ...label2 && { label: { en: label2 } },
3576
3617
  /** Carry the image-swap flag only on gift tiers that set it — the client shows the gift's product image in the step slot instead of the bag icon. */
3577
3618
  ...gift && tier.productTierImage && { productTierImage: true },
@@ -430,6 +430,20 @@ var SmartCartTier = z5.looseObject({
430
430
  productAmountRemainingLabel: z5.boolean().optional(),
431
431
  productAmountRemainingLabelText: z5.string().optional(),
432
432
  products: z5.array(SmartCartTierProduct).optional(),
433
+ /**
434
+ * onsite `product_tier_element_size`: the step-row icon's square size as a px STRING (`'18px'` …
435
+ * `'36px'` — the admin's five-value Size control, default `'18px'`). React stamps it onto the icon
436
+ * SVG's `width`/`height` (`getProgressStepIconSize`), so the milestone renders at the merchant's
437
+ * chosen size; the converter turns it into `CABProgressTier.iconSizePx` for the CAB renderer.
438
+ *
439
+ * `.catch(undefined)` for the same blast-radius reason as `productTierImage` below: this key was
440
+ * previously unknown-and-ignored by the `looseObject`, and `SmartCartConfig` is parsed
441
+ * `.nullish().catch(undefined)` with no intermediate catch, so one drifted value (a bare number, a
442
+ * `'2rem'`) would drop EVERY progress bar for the shop rather than just this setting. Failing open to
443
+ * `undefined` lands on the documented 18px default — strictly safer than that blast radius. The
444
+ * converter parses the number out and clamps it, so a junk-but-string value degrades the same way.
445
+ */
446
+ productTierElementSize: z5.string().optional().catch(void 0),
433
447
  /**
434
448
  * onsite `product_tier_image`: on a product (gift) tier, show the gift's product image in the step-row
435
449
  * slot instead of the generic bag icon (React `TierProgressIcon` swaps in the image when this is set and
@@ -1609,6 +1623,25 @@ var CABProgressTier = z21.object({
1609
1623
  title: z21.string().optional(),
1610
1624
  variantIds: z21.array(z21.number().int().positive()).default(() => [])
1611
1625
  }).optional(),
1626
+ /**
1627
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1628
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1629
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1630
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1631
+ *
1632
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1633
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1634
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1635
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1636
+ *
1637
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1638
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1639
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1640
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1641
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1642
+ * React's size rather than the old hardcoded 20.
1643
+ */
1644
+ iconSizePx: z21.number().int().min(1).max(64).default(18),
1612
1645
  /**
1613
1646
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1614
1647
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -3482,6 +3515,7 @@ var feedbackDoc = (raw, tokens) => ({
3482
3515
  ],
3483
3516
  type: "doc"
3484
3517
  });
3518
+ var MAX_ICON_SIZE_PX = 64;
3485
3519
  var IN_SCOPE_TIER_TYPES = new Set(progressTierTypes);
3486
3520
  var inScope = (tier) => IN_SCOPE_TIER_TYPES.has(tier.type ?? "");
3487
3521
  var thresholdOf = (tier) => tier.unlockConditionType === "item_quantity" ? Math.ceil(Number(tier.minimum)) : Math.round(Number(tier.minimum) * 100);
@@ -3500,6 +3534,10 @@ var discountOf = (tier) => {
3500
3534
  const amount = tier.discountAmountFromTotal ?? 0;
3501
3535
  return tier.discountType === "fixedAmount" ? { amount: Math.round(amount * 100), type: "fixedAmount" } : { amount, type: "percentage" };
3502
3536
  };
3537
+ var iconSizeOf = (tier) => {
3538
+ const px = Math.round(Number.parseFloat(String(tier.productTierElementSize ?? "")));
3539
+ return Number.isFinite(px) && px > 0 ? Math.min(px, MAX_ICON_SIZE_PX) : void 0;
3540
+ };
3503
3541
  var giftOf = (tier) => {
3504
3542
  if (tier.type !== "product") return void 0;
3505
3543
  const product = tier.products?.[0] ?? tier.allProducts?.[0];
@@ -3516,6 +3554,7 @@ var giftOf = (tier) => {
3516
3554
  var toTierMeta = (tier) => {
3517
3555
  const discount = discountOf(tier);
3518
3556
  const gift = giftOf(tier);
3557
+ const iconSizePx = iconSizeOf(tier);
3519
3558
  const isItemCount = tier.unlockConditionType === "item_quantity";
3520
3559
  const label2 = tierLabel(tier);
3521
3560
  const type = tier.type;
@@ -3524,6 +3563,8 @@ var toTierMeta = (tier) => {
3524
3563
  /** Carry the OOS-filter flag only on gift tiers that set it — the client drops the tier when its gift is fully out of stock. */
3525
3564
  ...gift && tier.filterOosVariants && { filterOosVariants: true },
3526
3565
  ...gift && { gift },
3566
+ /** Carry the merchant's milestone icon size only when set — absent ⇒ the schema's 18px (React) default. */
3567
+ ...iconSizePx !== void 0 && { iconSizePx },
3527
3568
  ...label2 && { label: { en: label2 } },
3528
3569
  /** Carry the image-swap flag only on gift tiers that set it — the client shows the gift's product image in the step slot instead of the bag icon. */
3529
3570
  ...gift && tier.productTierImage && { productTierImage: true },
@@ -1108,6 +1108,25 @@ var CABProgressTier = import_zod15.z.object({
1108
1108
  title: import_zod15.z.string().optional(),
1109
1109
  variantIds: import_zod15.z.array(import_zod15.z.number().int().positive()).default(() => [])
1110
1110
  }).optional(),
1111
+ /**
1112
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1113
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1114
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1115
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1116
+ *
1117
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1118
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1119
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1120
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1121
+ *
1122
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1123
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1124
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1125
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1126
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1127
+ * React's size rather than the old hardcoded 20.
1128
+ */
1129
+ iconSizePx: import_zod15.z.number().int().min(1).max(64).default(18),
1111
1130
  /**
1112
1131
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1113
1132
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -3412,6 +3431,7 @@ var feedbackDoc = (raw, tokens) => ({
3412
3431
  ],
3413
3432
  type: "doc"
3414
3433
  });
3434
+ var MAX_ICON_SIZE_PX = 64;
3415
3435
  var IN_SCOPE_TIER_TYPES = new Set(progressTierTypes);
3416
3436
  var inScope = (tier) => IN_SCOPE_TIER_TYPES.has(tier.type ?? "");
3417
3437
  var thresholdOf = (tier) => tier.unlockConditionType === "item_quantity" ? Math.ceil(Number(tier.minimum)) : Math.round(Number(tier.minimum) * 100);
@@ -3430,6 +3450,10 @@ var discountOf = (tier) => {
3430
3450
  const amount = tier.discountAmountFromTotal ?? 0;
3431
3451
  return tier.discountType === "fixedAmount" ? { amount: Math.round(amount * 100), type: "fixedAmount" } : { amount, type: "percentage" };
3432
3452
  };
3453
+ var iconSizeOf = (tier) => {
3454
+ const px = Math.round(Number.parseFloat(String(tier.productTierElementSize ?? "")));
3455
+ return Number.isFinite(px) && px > 0 ? Math.min(px, MAX_ICON_SIZE_PX) : void 0;
3456
+ };
3433
3457
  var giftOf = (tier) => {
3434
3458
  if (tier.type !== "product") return void 0;
3435
3459
  const product = tier.products?.[0] ?? tier.allProducts?.[0];
@@ -3446,6 +3470,7 @@ var giftOf = (tier) => {
3446
3470
  var toTierMeta = (tier) => {
3447
3471
  const discount = discountOf(tier);
3448
3472
  const gift = giftOf(tier);
3473
+ const iconSizePx = iconSizeOf(tier);
3449
3474
  const isItemCount = tier.unlockConditionType === "item_quantity";
3450
3475
  const label = tierLabel(tier);
3451
3476
  const type = tier.type;
@@ -3454,6 +3479,8 @@ var toTierMeta = (tier) => {
3454
3479
  /** Carry the OOS-filter flag only on gift tiers that set it — the client drops the tier when its gift is fully out of stock. */
3455
3480
  ...gift && tier.filterOosVariants && { filterOosVariants: true },
3456
3481
  ...gift && { gift },
3482
+ /** Carry the merchant's milestone icon size only when set — absent ⇒ the schema's 18px (React) default. */
3483
+ ...iconSizePx !== void 0 && { iconSizePx },
3457
3484
  ...label && { label: { en: label } },
3458
3485
  /** Carry the image-swap flag only on gift tiers that set it — the client shows the gift's product image in the step slot instead of the bag icon. */
3459
3486
  ...gift && tier.productTierImage && { productTierImage: true },
@@ -1051,6 +1051,25 @@ var CABProgressTier = z15.object({
1051
1051
  title: z15.string().optional(),
1052
1052
  variantIds: z15.array(z15.number().int().positive()).default(() => [])
1053
1053
  }).optional(),
1054
+ /**
1055
+ * The step-row icon's square size in PIXELS (onsite `product_tier_element_size`, an admin px string the
1056
+ * converter parses): 18 (default) / 20 / 24 / 30 / 36. React sizes the milestone by stamping this onto
1057
+ * the icon SVG's `width`/`height` (`getProgressStepIconSize`), so a merchant who deliberately enlarged
1058
+ * their milestones keeps that at checkout instead of every icon collapsing to one hardcoded square.
1059
+ *
1060
+ * A NUMBER, not the raw `'18px'` string: the renderer needs it as a length for the icon slot's grid
1061
+ * track, and a px-suffixed string would push unit parsing into every consumer. Deliberately NOT named
1062
+ * `iconSize` — the `iconSize` on an `image` section is the `s-icon` token enum, and one name covering both a
1063
+ * token and a pixel count is the kind of ambiguity that gets one passed where the other is meant.
1064
+ *
1065
+ * Bounded (not merely positive) because it is a raw merchant-controlled length: the step row is a grid
1066
+ * of per-tier cells, and an out-of-domain value would stretch the row rather than fail loudly. The
1067
+ * converter clamps to this same ceiling, so drifted config lands on a big-but-sane icon and never on a
1068
+ * tier the strict parse drops. `.default(18)` holds React's default at parse time (schema-first — the
1069
+ * renderer never spells a fallback), which also makes a tree authored before this field render at
1070
+ * React's size rather than the old hardcoded 20.
1071
+ */
1072
+ iconSizePx: z15.number().int().min(1).max(64).default(18),
1054
1073
  /**
1055
1074
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
1056
1075
  * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
@@ -3355,6 +3374,7 @@ var feedbackDoc = (raw, tokens) => ({
3355
3374
  ],
3356
3375
  type: "doc"
3357
3376
  });
3377
+ var MAX_ICON_SIZE_PX = 64;
3358
3378
  var IN_SCOPE_TIER_TYPES = new Set(progressTierTypes);
3359
3379
  var inScope = (tier) => IN_SCOPE_TIER_TYPES.has(tier.type ?? "");
3360
3380
  var thresholdOf = (tier) => tier.unlockConditionType === "item_quantity" ? Math.ceil(Number(tier.minimum)) : Math.round(Number(tier.minimum) * 100);
@@ -3373,6 +3393,10 @@ var discountOf = (tier) => {
3373
3393
  const amount = tier.discountAmountFromTotal ?? 0;
3374
3394
  return tier.discountType === "fixedAmount" ? { amount: Math.round(amount * 100), type: "fixedAmount" } : { amount, type: "percentage" };
3375
3395
  };
3396
+ var iconSizeOf = (tier) => {
3397
+ const px = Math.round(Number.parseFloat(String(tier.productTierElementSize ?? "")));
3398
+ return Number.isFinite(px) && px > 0 ? Math.min(px, MAX_ICON_SIZE_PX) : void 0;
3399
+ };
3376
3400
  var giftOf = (tier) => {
3377
3401
  if (tier.type !== "product") return void 0;
3378
3402
  const product = tier.products?.[0] ?? tier.allProducts?.[0];
@@ -3389,6 +3413,7 @@ var giftOf = (tier) => {
3389
3413
  var toTierMeta = (tier) => {
3390
3414
  const discount = discountOf(tier);
3391
3415
  const gift = giftOf(tier);
3416
+ const iconSizePx = iconSizeOf(tier);
3392
3417
  const isItemCount = tier.unlockConditionType === "item_quantity";
3393
3418
  const label = tierLabel(tier);
3394
3419
  const type = tier.type;
@@ -3397,6 +3422,8 @@ var toTierMeta = (tier) => {
3397
3422
  /** Carry the OOS-filter flag only on gift tiers that set it — the client drops the tier when its gift is fully out of stock. */
3398
3423
  ...gift && tier.filterOosVariants && { filterOosVariants: true },
3399
3424
  ...gift && { gift },
3425
+ /** Carry the merchant's milestone icon size only when set — absent ⇒ the schema's 18px (React) default. */
3426
+ ...iconSizePx !== void 0 && { iconSizePx },
3400
3427
  ...label && { label: { en: label } },
3401
3428
  /** Carry the image-swap flag only on gift tiers that set it — the client shows the gift's product image in the step slot instead of the bag icon. */
3402
3429
  ...gift && tier.productTierImage && { productTierImage: true },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebuy/rebuy",
3
- "version": "3.11.0",
3
+ "version": "3.12.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.",