@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
@@ -47,6 +47,7 @@ var borderWidths = ["base", "medium", "thick"];
47
47
  var BorderWidth = freezeEnum(borderWidths);
48
48
  var buttonActions = [
49
49
  "acceptOffer",
50
+ "addGift",
50
51
  "addToOrder",
51
52
  "declineAllOffers",
52
53
  "declineOffer",
@@ -56,6 +57,7 @@ var buttonActions = [
56
57
  "goToPrevPage",
57
58
  "goToURL",
58
59
  "removeFromOrder",
60
+ "removeGift",
59
61
  "selectVariant",
60
62
  "showPagination",
61
63
  "switchToSubscription",
@@ -348,22 +350,10 @@ var import_zod20 = require("zod");
348
350
 
349
351
  // src/schema/widgets/checkout-and-beyond/banner.ts
350
352
  var import_zod4 = require("zod");
351
- var CABBannerSection = import_zod4.z.lazy(
352
- () => CABLayoutSection.omit({ sectionType: true }).extend({
353
- buttonField: import_zod4.z.enum(buttonFields).optional(),
354
- color: import_zod4.z.enum(bannerColors).default("info"),
355
- dismissible: import_zod4.z.boolean().default(true),
356
- sectionType: import_zod4.z.literal(SectionType.banner).default(SectionType.banner)
357
- })
358
- );
359
353
 
360
- // src/schema/widgets/checkout-and-beyond/button.ts
361
- var import_uuid3 = require("uuid");
362
- var import_zod7 = require("zod");
363
-
364
- // src/schema/widgets/checkout-and-beyond/image.ts
365
- var import_uuid = require("uuid");
366
- var import_zod5 = require("zod");
354
+ // src/schema/widgets/checkout-and-beyond/utils.ts
355
+ var import_es_toolkit2 = require("es-toolkit");
356
+ var import_compat = require("es-toolkit/compat");
367
357
 
368
358
  // src/schema/widgets/checkout-and-beyond/regex.ts
369
359
  var DYNAMIC_TOKEN_REGEX = /^\{\{\s*[A-Za-z]+\s*\}\}$/;
@@ -372,8 +362,6 @@ var ROOT_RELATIVE_PATH_REGEX = /^\/(?!\/)/;
372
362
  var HTML_TAGS_REGEX = /<\/?[a-zA-Z][^>]*>/g;
373
363
 
374
364
  // src/schema/widgets/checkout-and-beyond/utils.ts
375
- var import_es_toolkit2 = require("es-toolkit");
376
- var import_compat = require("es-toolkit/compat");
377
365
  var isHTML = (html = "") => {
378
366
  if (typeof window !== "undefined") {
379
367
  const parser = new DOMParser();
@@ -387,13 +375,158 @@ var hasHTMLInDoc = (doc) => doc.content.some(({ content = [] }) => content.some(
387
375
  var checkForHTML = (input) => !((0, import_compat.isString)(input) && isHTML(input) || (0, import_es_toolkit2.isPlainObject)(input) && hasHTMLInDoc(input));
388
376
  var NO_HTML = { message: "HTML is not supported" };
389
377
 
378
+ // src/schema/widgets/checkout-and-beyond/banner.ts
379
+ var CABBannerSection = import_zod4.z.lazy(
380
+ () => CABLayoutSection.omit({ sectionType: true }).extend({
381
+ buttonField: import_zod4.z.enum(buttonFields).optional(),
382
+ color: import_zod4.z.enum(bannerColors).default("info"),
383
+ dismissible: import_zod4.z.boolean().default(true),
384
+ /**
385
+ * The `s-banner` heading — localized content (a buyer can see a merchant-composed banner). Absent OR
386
+ * blank ⇒ no heading; the renderer emits no heading slot for `''` rather than an empty one.
387
+ *
388
+ * Merchant-composed buyer-facing plain text, so it rejects HTML at the boundary the same way
389
+ * `CABImageSection.altText` and `CABTextSection.content` do (the unchecked localized records elsewhere —
390
+ * `progressBar`'s gift labels, `reviews`' plurals — are converter/constant-sourced, not merchant input).
391
+ *
392
+ * The refinement is a last-resort ASSERTION, not the normalization boundary: `normalizeTextContent` only
393
+ * rewrites `sectionType: 'text'` nodes' `content`, so nothing strips markup or canonicalizes `{token}`
394
+ * here. A producer must strip upstream the way `composeOffer` does for `altText`. Get it wrong and
395
+ * `salvageSections` stubs the whole banner (children included) with a drift report — degraded, reported,
396
+ * not a 500. Nothing emits `heading` yet; the first converter that maps merchant banner copy into it
397
+ * either strips first or teaches `normalizeTextContent` to strip this field.
398
+ */
399
+ heading: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.string().refine(checkForHTML, NO_HTML)).optional(),
400
+ sectionType: import_zod4.z.literal(SectionType.banner).default(SectionType.banner)
401
+ })
402
+ );
403
+
404
+ // src/schema/widgets/checkout-and-beyond/button.ts
405
+ var import_uuid3 = require("uuid");
406
+ var import_zod7 = require("zod");
407
+
408
+ // src/schema/widgets/checkout-and-beyond/image.ts
409
+ var import_uuid = require("uuid");
410
+ var import_zod5 = require("zod");
411
+
412
+ // src/schema/widgets/checkout-and-beyond/icons.ts
413
+ var iconNames = [
414
+ "alert-circle",
415
+ "alert-triangle",
416
+ "alert-triangle-filled",
417
+ "arrow-down",
418
+ "arrow-left",
419
+ "arrow-right",
420
+ "arrow-up",
421
+ "arrow-up-right",
422
+ "bag",
423
+ "bullet",
424
+ "calendar",
425
+ "camera",
426
+ "caret-down",
427
+ "cart",
428
+ "cash-dollar",
429
+ "categories",
430
+ "check",
431
+ "check-circle",
432
+ "check-circle-filled",
433
+ "chevron-down",
434
+ "chevron-left",
435
+ "chevron-right",
436
+ "chevron-up",
437
+ "circle",
438
+ "clipboard",
439
+ "clock",
440
+ "credit-card",
441
+ "delete",
442
+ "delivered",
443
+ "delivery",
444
+ "disabled",
445
+ "discount",
446
+ "edit",
447
+ "email",
448
+ "empty",
449
+ "external",
450
+ "filter",
451
+ "geolocation",
452
+ "gift-card",
453
+ "globe",
454
+ "grid",
455
+ "image",
456
+ "info",
457
+ "info-filled",
458
+ "list-bulleted",
459
+ "location",
460
+ "lock",
461
+ "map",
462
+ "menu",
463
+ "menu-horizontal",
464
+ "menu-vertical",
465
+ "minus",
466
+ "mobile",
467
+ "note",
468
+ "order",
469
+ "organization",
470
+ "plus",
471
+ "profile",
472
+ "question-circle",
473
+ "question-circle-filled",
474
+ "reorder",
475
+ "reset",
476
+ "return",
477
+ "savings",
478
+ "search",
479
+ "settings",
480
+ "star",
481
+ "star-filled",
482
+ "star-half",
483
+ "store",
484
+ "truck",
485
+ "upload",
486
+ "x",
487
+ "x-circle",
488
+ "x-circle-filled"
489
+ ];
490
+ var IconName = freezeEnum(iconNames);
491
+ var iconSizes = ["base", "large", "large-100", "small", "small-100", "small-200"];
492
+ var IconSize = freezeEnum(iconSizes);
493
+ var iconTones = ["auto", "critical", "custom", "info", "neutral", "success", "warning"];
494
+ var IconTone = freezeEnum(iconTones);
495
+
390
496
  // src/schema/widgets/checkout-and-beyond/image.ts
391
- var CABImageSection = import_zod5.z.object({
497
+ var CABImageSectionFields = import_zod5.z.object({
392
498
  altText: import_zod5.z.string().refine(checkForHTML, NO_HTML).default(""),
393
- aspectRatio: import_zod5.z.literal(1).nullable().default(null),
499
+ /**
500
+ * Image width÷height (e.g. `46` for the progress-bar fill); `null` renders at natural size. Any POSITIVE
501
+ * ratio — never limited to 1, but never `0`/negative either: a renderer dividing by it would get `Infinity`,
502
+ * and CSS `aspect-ratio` drops a negative value and silently reverts to natural size.
503
+ */
504
+ aspectRatio: import_zod5.z.number().positive().nullable().default(null),
394
505
  border: import_zod5.z.lazy(() => CABBorder),
395
506
  buttonField: import_zod5.z.enum(buttonFields).optional(),
396
- category: import_zod5.z.enum(["gallery", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
507
+ /**
508
+ * `icon` renders `source` as a single `s-icon` by name (the uber-image path covers icons too), reading
509
+ * `iconSize`/`iconTone`. The other values are a harmless informational holdover from the previous
510
+ * implementation — they were never significant to rendering (`icons`, plural, is NOT deprecated, just one of
511
+ * those inert legacy tags); `icon` is the first value that means anything.
512
+ *
513
+ * INVARIANT, encoded by the `.superRefine` below (a refined object IS a valid `z.discriminatedUnion` member
514
+ * in zod 4 — see `CABTextSection`): `category: 'icon'` ⇒ `source` is an icon name or `''` (icon not yet
515
+ * chosen); any other category ⇒ `source` is NOT a bare icon name, so it stays a URL/token/`''`.
516
+ *
517
+ * Encoded rather than left to the renderer because `source` is ONE union with no category gate, so widening
518
+ * it with `iconNames` also widened what a STORED payload may contain: 14 of the names are plain English
519
+ * words (`image`, `x`, `search`, `note`, `order`, `globe`, …), and a legacy `source: 'image'` used to fail
520
+ * parse — which `salvageSections` turns into a null-rendering stub PLUS a drift report. Ungated it would
521
+ * instead parse and reach the renderer as `<img src="image">`: a broken image, silently, where the old
522
+ * behavior degraded gracefully and told us about it. The client-assembled half of the invariant was never
523
+ * the risky half.
524
+ */
525
+ category: import_zod5.z.enum(["gallery", "icon", "icons", "payment-methods", "secure-checkout"]).nullable().default(null),
526
+ /** `icon`-mode only: the `s-icon` `size`; `null` ⇒ the component default (`base`). Ignored by image treatments. */
527
+ iconSize: import_zod5.z.enum(iconSizes).nullable().default(null),
528
+ /** `icon`-mode only: the `s-icon` `tone`; `null` ⇒ the component default (`auto`). Ignored by image treatments. */
529
+ iconTone: import_zod5.z.enum(iconTones).nullable().default(null),
397
530
  name: import_zod5.z.string().optional(),
398
531
  naturalHeight: import_zod5.z.number().default(0),
399
532
  naturalWidth: import_zod5.z.number().default(0),
@@ -405,9 +538,31 @@ var CABImageSection = import_zod5.z.object({
405
538
  rule: CABRule.optional(),
406
539
  sectionId: import_zod5.z.uuid().default(() => (0, import_uuid.v7)()),
407
540
  sectionType: import_zod5.z.literal(SectionType.image).default(SectionType.image),
408
- source: import_zod5.z.union([import_zod5.z.url(), import_zod5.z.literal(""), import_zod5.z.string().regex(DYNAMIC_TOKEN_REGEX)]).default(""),
541
+ /**
542
+ * An image URL or dynamic token, an empty default, or — when `category: 'icon'` — an icon NAME. Icon mode
543
+ * takes a name or `''` only, NOT a token: no renderer resolves a token to an icon today, so accepting one
544
+ * would promise a capability that doesn't exist. Widen the refine's carve-out to `DYNAMIC_TOKEN_REGEX` when a
545
+ * server-chosen tier icon actually needs it.
546
+ */
547
+ source: import_zod5.z.union([import_zod5.z.url(), import_zod5.z.literal(""), import_zod5.z.string().regex(DYNAMIC_TOKEN_REGEX), import_zod5.z.enum(iconNames)]).default(""),
409
548
  width: import_zod5.z.number().default(100)
410
549
  });
550
+ var iconNameSet = new Set(iconNames);
551
+ var isIconName = (source) => iconNameSet.has(source);
552
+ var CABImageSection = CABImageSectionFields.superRefine(({ category, source }, ctx) => {
553
+ if (category === "icon" && source !== "" && !isIconName(source))
554
+ ctx.addIssue({
555
+ code: "custom",
556
+ message: "icon-mode source must be an icon name",
557
+ path: ["source"]
558
+ });
559
+ if (category !== "icon" && isIconName(source))
560
+ ctx.addIssue({
561
+ code: "custom",
562
+ message: "source must be a URL or dynamic token unless category is `icon`",
563
+ path: ["source"]
564
+ });
565
+ });
411
566
 
412
567
  // src/schema/widgets/checkout-and-beyond/text.ts
413
568
  var import_compat2 = require("es-toolkit/compat");
@@ -527,6 +682,21 @@ var CABButtonSection = import_zod7.z.object({
527
682
  sectionId: import_zod7.z.uuid().default(() => (0, import_uuid3.v7)()),
528
683
  sections: import_zod7.z.union([import_zod7.z.array(CABButtonContent), import_zod7.z.strictObject({}).transform(() => [])]).default(() => []),
529
684
  sectionType: import_zod7.z.literal(SectionType.button).default(SectionType.button),
685
+ /**
686
+ * The smart-cart tier this button acts on (`addGift`/`removeGift`): scopes the click to one tier's gift. The
687
+ * client resolves the tier's gift (productId) from the progress-bar context by this `tierId` — the button node
688
+ * stays data, no bespoke per-tier wiring. Absent on non-gift buttons (offer add/remove, navigation, links).
689
+ *
690
+ * Deliberately NOT `CABTextTier` (the shape `CABTextSection.tier` uses): a gift button acts on a tier the bar
691
+ * already resolved, so it needs the id and nothing else. Reusing the text tier would make `threshold`
692
+ * required, leave `tierId` optional, and DEFAULT `tierType` to `'shipping'` — a schema-supplied wrong answer
693
+ * on a gift button. Unknown keys are stripped, so a client spreading a whole tier in still parses.
694
+ *
695
+ * `.min(1)` because an empty id IS the silently-id-less state this shape exists to prevent: the client's
696
+ * lookup finds no tier and the click resolves to nothing. Safe to bound — the field is new, so there are no
697
+ * stored payloads to grandfather, and the producer is client code, not a merchant form.
698
+ */
699
+ tier: import_zod7.z.object({ tierId: import_zod7.z.string().min(1) }).optional(),
530
700
  /** Fire-and-forget pixel POSTed when the button is clicked (e.g. a Monetize decline). */
531
701
  trackingUrl: import_zod7.z.string().optional()
532
702
  });
@@ -822,8 +992,12 @@ var CABProgressTier = import_zod16.z.object({
822
992
  }).optional(),
823
993
  /**
824
994
  * The step-row label at this tier's slot (onsite `getTierLabel`): the merchant custom label, else the
825
- * type default ('Free Shipping' / product title / '{n}% Discount'). Localized content; blank ⇒ no
826
- * label under the tier's icon. Plain text — the step row is a compact icon+label, not rich copy.
995
+ * type default — 'Free Shipping' or '{n}% Discount'. A PRODUCT tier gets NO converter label: its name is
996
+ * the gift PRODUCT title, which the converter can't supply (config carries only product IDs), so the
997
+ * client resolves it (authoritative Shopify title, React parity) with its own localized generic fallback.
998
+ * Localized content; absent OR blank ⇒ no label under the tier's icon (the converter's `toTierMeta` already
999
+ * turns a blank label into an absent key, and a client-authored blank means the same thing — the renderer
1000
+ * emits no caption slot rather than an empty one). Plain text — a compact icon+label.
827
1001
  */
828
1002
  label: import_zod16.z.record(import_zod16.z.string(), import_zod16.z.string()).optional(),
829
1003
  /**