@rebuy/rebuy 2.34.0 → 2.35.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 (43) hide show
  1. package/dist/index.js +204 -23
  2. package/dist/index.js.map +4 -4
  3. package/dist/index.mjs +204 -23
  4. package/dist/index.mjs.map +4 -4
  5. package/dist/schema/checkout-and-beyond/constants.js +2 -0
  6. package/dist/schema/checkout-and-beyond/constants.js.map +2 -2
  7. package/dist/schema/checkout-and-beyond/constants.mjs +2 -0
  8. package/dist/schema/checkout-and-beyond/constants.mjs.map +2 -2
  9. package/dist/schema/checkout-and-beyond/index.js +183 -6
  10. package/dist/schema/checkout-and-beyond/index.js.map +3 -3
  11. package/dist/schema/checkout-and-beyond/index.mjs +183 -6
  12. package/dist/schema/checkout-and-beyond/index.mjs.map +3 -3
  13. package/dist/schema/widget-data.js +197 -23
  14. package/dist/schema/widget-data.js.map +4 -4
  15. package/dist/schema/widget-data.mjs +197 -23
  16. package/dist/schema/widget-data.mjs.map +3 -3
  17. package/dist/schema/widgets/checkout-and-beyond/banner.d.ts +27 -25
  18. package/dist/schema/widgets/checkout-and-beyond/banner.d.ts.map +1 -1
  19. package/dist/schema/widgets/checkout-and-beyond/button.d.ts +5 -0
  20. package/dist/schema/widgets/checkout-and-beyond/button.d.ts.map +1 -1
  21. package/dist/schema/widgets/checkout-and-beyond/carousel.d.ts +25 -25
  22. package/dist/schema/widgets/checkout-and-beyond/cartLine.d.ts +25 -25
  23. package/dist/schema/widgets/checkout-and-beyond/common.d.ts +3 -1
  24. package/dist/schema/widgets/checkout-and-beyond/common.d.ts.map +1 -1
  25. package/dist/schema/widgets/checkout-and-beyond/icons.d.ts +124 -0
  26. package/dist/schema/widgets/checkout-and-beyond/icons.d.ts.map +1 -0
  27. package/dist/schema/widgets/checkout-and-beyond/image.d.ts +319 -2
  28. package/dist/schema/widgets/checkout-and-beyond/image.d.ts.map +1 -1
  29. package/dist/schema/widgets/checkout-and-beyond/index.d.ts +1 -0
  30. package/dist/schema/widgets/checkout-and-beyond/index.d.ts.map +1 -1
  31. package/dist/schema/widgets/checkout-and-beyond/offers.d.ts +25 -25
  32. package/dist/schema/widgets/checkout-and-beyond/progressBar.d.ts +25 -25
  33. package/dist/schema/widgets/checkout-and-beyond/progressBar.d.ts.map +1 -1
  34. package/dist/server/index.js +193 -25
  35. package/dist/server/index.js.map +4 -4
  36. package/dist/server/index.mjs +193 -25
  37. package/dist/server/index.mjs.map +4 -4
  38. package/dist/transforms/index.js +193 -25
  39. package/dist/transforms/index.js.map +3 -3
  40. package/dist/transforms/index.mjs +193 -25
  41. package/dist/transforms/index.mjs.map +3 -3
  42. package/dist/transforms/smartCart/convertSmartCartProgressBarToV2.d.ts.map +1 -1
  43. package/package.json +1 -1
@@ -13,6 +13,7 @@ var borderWidths = ["base", "medium", "thick"];
13
13
  var BorderWidth = freezeEnum(borderWidths);
14
14
  var buttonActions = [
15
15
  "acceptOffer",
16
+ "addGift",
16
17
  "addToOrder",
17
18
  "declineAllOffers",
18
19
  "declineOffer",
@@ -22,6 +23,7 @@ var buttonActions = [
22
23
  "goToPrevPage",
23
24
  "goToURL",
24
25
  "removeFromOrder",
26
+ "removeGift",
25
27
  "selectVariant",
26
28
  "showPagination",
27
29
  "switchToSubscription",
@@ -239,6 +241,90 @@ import { z as z4 } from "zod";
239
241
  import { v7 as uuidv7 } from "uuid";
240
242
  import { z as z2 } from "zod";
241
243
 
244
+ // src/schema/widgets/checkout-and-beyond/icons.ts
245
+ var iconNames = [
246
+ "alert-circle",
247
+ "alert-triangle",
248
+ "alert-triangle-filled",
249
+ "arrow-down",
250
+ "arrow-left",
251
+ "arrow-right",
252
+ "arrow-up",
253
+ "arrow-up-right",
254
+ "bag",
255
+ "bullet",
256
+ "calendar",
257
+ "camera",
258
+ "caret-down",
259
+ "cart",
260
+ "cash-dollar",
261
+ "categories",
262
+ "check",
263
+ "check-circle",
264
+ "check-circle-filled",
265
+ "chevron-down",
266
+ "chevron-left",
267
+ "chevron-right",
268
+ "chevron-up",
269
+ "circle",
270
+ "clipboard",
271
+ "clock",
272
+ "credit-card",
273
+ "delete",
274
+ "delivered",
275
+ "delivery",
276
+ "disabled",
277
+ "discount",
278
+ "edit",
279
+ "email",
280
+ "empty",
281
+ "external",
282
+ "filter",
283
+ "geolocation",
284
+ "gift-card",
285
+ "globe",
286
+ "grid",
287
+ "image",
288
+ "info",
289
+ "info-filled",
290
+ "list-bulleted",
291
+ "location",
292
+ "lock",
293
+ "map",
294
+ "menu",
295
+ "menu-horizontal",
296
+ "menu-vertical",
297
+ "minus",
298
+ "mobile",
299
+ "note",
300
+ "order",
301
+ "organization",
302
+ "plus",
303
+ "profile",
304
+ "question-circle",
305
+ "question-circle-filled",
306
+ "reorder",
307
+ "reset",
308
+ "return",
309
+ "savings",
310
+ "search",
311
+ "settings",
312
+ "star",
313
+ "star-filled",
314
+ "star-half",
315
+ "store",
316
+ "truck",
317
+ "upload",
318
+ "x",
319
+ "x-circle",
320
+ "x-circle-filled"
321
+ ];
322
+ var IconName = freezeEnum(iconNames);
323
+ var iconSizes = ["base", "large", "large-100", "small", "small-100", "small-200"];
324
+ var IconSize = freezeEnum(iconSizes);
325
+ var iconTones = ["auto", "critical", "custom", "info", "neutral", "success", "warning"];
326
+ var IconTone = freezeEnum(iconTones);
327
+
242
328
  // src/schema/widgets/checkout-and-beyond/regex.ts
243
329
  var ARRAY_INDEX_STRING = /^(0|[1-9]\d*)$/;
244
330
  var DYNAMIC_TOKEN_REGEX = /^\{\{\s*[A-Za-z]+\s*\}\}$/;
@@ -291,12 +377,39 @@ var convertNumericObjects = (input) => {
291
377
  };
292
378
 
293
379
  // src/schema/widgets/checkout-and-beyond/image.ts
294
- var CABImageSection = z2.object({
380
+ var CABImageSectionFields = z2.object({
295
381
  altText: z2.string().refine(checkForHTML, NO_HTML).default(""),
296
- aspectRatio: z2.literal(1).nullable().default(null),
382
+ /**
383
+ * Image width÷height (e.g. `46` for the progress-bar fill); `null` renders at natural size. Any POSITIVE
384
+ * ratio — never limited to 1, but never `0`/negative either: a renderer dividing by it would get `Infinity`,
385
+ * and CSS `aspect-ratio` drops a negative value and silently reverts to natural size.
386
+ */
387
+ aspectRatio: z2.number().positive().nullable().default(null),
297
388
  border: z2.lazy(() => CABBorder),
298
389
  buttonField: z2.enum(buttonFields).optional(),
299
- category: z2.enum(["gallery", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
390
+ /**
391
+ * `icon` renders `source` as a single `s-icon` by name (the uber-image path covers icons too), reading
392
+ * `iconSize`/`iconTone`. The other values are a harmless informational holdover from the previous
393
+ * implementation — they were never significant to rendering (`icons`, plural, is NOT deprecated, just one of
394
+ * those inert legacy tags); `icon` is the first value that means anything.
395
+ *
396
+ * INVARIANT, encoded by the `.superRefine` below (a refined object IS a valid `z.discriminatedUnion` member
397
+ * in zod 4 — see `CABTextSection`): `category: 'icon'` ⇒ `source` is an icon name or `''` (icon not yet
398
+ * chosen); any other category ⇒ `source` is NOT a bare icon name, so it stays a URL/token/`''`.
399
+ *
400
+ * Encoded rather than left to the renderer because `source` is ONE union with no category gate, so widening
401
+ * it with `iconNames` also widened what a STORED payload may contain: 14 of the names are plain English
402
+ * words (`image`, `x`, `search`, `note`, `order`, `globe`, …), and a legacy `source: 'image'` used to fail
403
+ * parse — which `salvageSections` turns into a null-rendering stub PLUS a drift report. Ungated it would
404
+ * instead parse and reach the renderer as `<img src="image">`: a broken image, silently, where the old
405
+ * behavior degraded gracefully and told us about it. The client-assembled half of the invariant was never
406
+ * the risky half.
407
+ */
408
+ category: z2.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
409
+ /** `icon`-mode only: the `s-icon` `size`; `null` ⇒ the component default (`base`). Ignored by image treatments. */
410
+ iconSize: z2.enum(iconSizes).nullable().default(null),
411
+ /** `icon`-mode only: the `s-icon` `tone`; `null` ⇒ the component default (`auto`). Ignored by image treatments. */
412
+ iconTone: z2.enum(iconTones).nullable().default(null),
300
413
  name: z2.string().optional(),
301
414
  naturalHeight: z2.number().default(0),
302
415
  naturalWidth: z2.number().default(0),
@@ -308,9 +421,31 @@ var CABImageSection = z2.object({
308
421
  rule: CABRule.optional(),
309
422
  sectionId: z2.uuid().default(() => uuidv7()),
310
423
  sectionType: z2.literal(SectionType.image).default(SectionType.image),
311
- source: z2.union([z2.url(), z2.literal(""), z2.string().regex(DYNAMIC_TOKEN_REGEX)]).default(""),
424
+ /**
425
+ * An image URL or dynamic token, an empty default, or — when `category: 'icon'` — an icon NAME. Icon mode
426
+ * takes a name or `''` only, NOT a token: no renderer resolves a token to an icon today, so accepting one
427
+ * would promise a capability that doesn't exist. Widen the refine's carve-out to `DYNAMIC_TOKEN_REGEX` when a
428
+ * server-chosen tier icon actually needs it.
429
+ */
430
+ source: z2.union([z2.url(), z2.literal(""), z2.string().regex(DYNAMIC_TOKEN_REGEX), z2.enum(iconNames)]).default(""),
312
431
  width: z2.number().default(100)
313
432
  });
433
+ var iconNameSet = new Set(iconNames);
434
+ var isIconName = (source) => iconNameSet.has(source);
435
+ var CABImageSection = CABImageSectionFields.superRefine(({ category, source }, ctx) => {
436
+ if (category === "icon" && source !== "" && !isIconName(source))
437
+ ctx.addIssue({
438
+ code: "custom",
439
+ message: "icon-mode source must be an icon name",
440
+ path: ["source"]
441
+ });
442
+ if (category !== "icon" && isIconName(source))
443
+ ctx.addIssue({
444
+ code: "custom",
445
+ message: "source must be a URL or dynamic token unless category is `icon`",
446
+ path: ["source"]
447
+ });
448
+ });
314
449
 
315
450
  // src/schema/widgets/checkout-and-beyond/text.ts
316
451
  import { forEach, isString as isString2 } from "es-toolkit/compat";
@@ -430,6 +565,21 @@ var CABButtonSection = z4.object({
430
565
  sectionId: z4.uuid().default(() => uuidv73()),
431
566
  sections: z4.union([z4.array(CABButtonContent), z4.strictObject({}).transform(() => [])]).default(() => []),
432
567
  sectionType: z4.literal(SectionType.button).default(SectionType.button),
568
+ /**
569
+ * The smart-cart tier this button acts on (`addGift`/`removeGift`): scopes the click to one tier's gift. The
570
+ * client resolves the tier's gift (productId) from the progress-bar context by this `tierId` — the button node
571
+ * stays data, no bespoke per-tier wiring. Absent on non-gift buttons (offer add/remove, navigation, links).
572
+ *
573
+ * Deliberately NOT `CABTextTier` (the shape `CABTextSection.tier` uses): a gift button acts on a tier the bar
574
+ * already resolved, so it needs the id and nothing else. Reusing the text tier would make `threshold`
575
+ * required, leave `tierId` optional, and DEFAULT `tierType` to `'shipping'` — a schema-supplied wrong answer
576
+ * on a gift button. Unknown keys are stripped, so a client spreading a whole tier in still parses.
577
+ *
578
+ * `.min(1)` because an empty id IS the silently-id-less state this shape exists to prevent: the client's
579
+ * lookup finds no tier and the click resolves to nothing. Safe to bound — the field is new, so there are no
580
+ * stored payloads to grandfather, and the producer is client code, not a merchant form.
581
+ */
582
+ tier: z4.object({ tierId: z4.string().min(1) }).optional(),
433
583
  /** Fire-and-forget pixel POSTed when the button is clicked (e.g. a Monetize decline). */
434
584
  trackingUrl: z4.string().optional()
435
585
  });
@@ -803,8 +953,12 @@ var CABProgressTier = z13.object({
803
953
  }).optional(),
804
954
  /**
805
955
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
806
- * type default ('Free Shipping' / product title / '{n}% Discount'). Localized content; blank ⇒ no
807
- * label under the tier's icon. Plain text — the step row is a compact icon+label, not rich copy.
956
+ * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
957
+ * the gift PRODUCT title, which the converter can't supply (config carries only product IDs), so the
958
+ * client resolves it (authoritative Shopify title, React parity) with its own localized generic fallback.
959
+ * Localized content; absent OR blank ⇒ no label under the tier's icon (the converter's `toTierMeta` already
960
+ * turns a blank label into an absent key, and a client-authored blank means the same thing — the renderer
961
+ * emits no caption slot rather than an empty one). Plain text — a compact icon+label.
808
962
  */
809
963
  label: z13.record(z13.string(), z13.string()).optional(),
810
964
  /**
@@ -1099,6 +1253,22 @@ var CABBannerSection = z19.lazy(
1099
1253
  buttonField: z19.enum(buttonFields).optional(),
1100
1254
  color: z19.enum(bannerColors).default("info"),
1101
1255
  dismissible: z19.boolean().default(true),
1256
+ /**
1257
+ * The `s-banner` heading — localized content (a buyer can see a merchant-composed banner). Absent OR
1258
+ * blank ⇒ no heading; the renderer emits no heading slot for `''` rather than an empty one.
1259
+ *
1260
+ * Merchant-composed buyer-facing plain text, so it rejects HTML at the boundary the same way
1261
+ * `CABImageSection.altText` and `CABTextSection.content` do (the unchecked localized records elsewhere —
1262
+ * `progressBar`'s gift labels, `reviews`' plurals — are converter/constant-sourced, not merchant input).
1263
+ *
1264
+ * The refinement is a last-resort ASSERTION, not the normalization boundary: `normalizeTextContent` only
1265
+ * rewrites `sectionType: 'text'` nodes' `content`, so nothing strips markup or canonicalizes `{token}`
1266
+ * here. A producer must strip upstream the way `composeOffer` does for `altText`. Get it wrong and
1267
+ * `salvageSections` stubs the whole banner (children included) with a drift report — degraded, reported,
1268
+ * not a 500. Nothing emits `heading` yet; the first converter that maps merchant banner copy into it
1269
+ * either strips first or teaches `normalizeTextContent` to strip this field.
1270
+ */
1271
+ heading: z19.record(z19.string(), z19.string().refine(checkForHTML, NO_HTML)).optional(),
1102
1272
  sectionType: z19.literal(SectionType.banner).default(SectionType.banner)
1103
1273
  })
1104
1274
  );
@@ -1508,6 +1678,7 @@ export {
1508
1678
  CABDiscountSection,
1509
1679
  CABExperiment,
1510
1680
  CABImageSection,
1681
+ CABImageSectionFields,
1511
1682
  CABIntegrations,
1512
1683
  CABLayoutSection,
1513
1684
  CABMonetizeSection,
@@ -1539,6 +1710,9 @@ export {
1539
1710
  HEX_COLOR_REGEX,
1540
1711
  HTML_TAGS_REGEX,
1541
1712
  HorizontalAlignment,
1713
+ IconName,
1714
+ IconSize,
1715
+ IconTone,
1542
1716
  LanguageKey,
1543
1717
  NO_HTML,
1544
1718
  OFFER_LABELS,
@@ -1586,6 +1760,9 @@ export {
1586
1760
  freezeEnum,
1587
1761
  hasHTMLInDoc,
1588
1762
  horizontalAlignments,
1763
+ iconNames,
1764
+ iconSizes,
1765
+ iconTones,
1589
1766
  isBannerType,
1590
1767
  isButtonType,
1591
1768
  isCarouselType,