@rebuy/rebuy 3.13.0 → 3.15.0-rc.1

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
@@ -2507,6 +2507,13 @@ var CABProductsSection = import_zod18.z.object({
2507
2507
  // src/schema/widgets/checkout-and-beyond/offers.ts
2508
2508
  var CABOffersSection = import_zod19.z.lazy(
2509
2509
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
2510
+ /**
2511
+ * A rule between consecutive cards in the vertical list — legacy checkout-offers' `<Divider />`,
2512
+ * which it drew whenever the per-card border was off (a borderless stack otherwise reads as one
2513
+ * run of products). Optional, not defaulted: only the v1 converter sets it (REB-24265); a
2514
+ * hand-built tree keeps React CAB's dividerless rendering.
2515
+ */
2516
+ divider: import_zod19.z.boolean().optional(),
2510
2517
  sections: import_zod19.z.union([import_zod19.z.array(import_zod19.z.lazy(() => CABSection)), import_zod19.z.strictObject({}).transform(() => [])]).default(() => [
2511
2518
  CABBannerSection.parse({
2512
2519
  buttonField: "undoAddToOrder",
@@ -3056,6 +3063,8 @@ var CABLayoutSection = import_zod29.z.object({
3056
3063
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
3057
3064
  var UI_LABELS = {
3058
3065
  currentPage: { en: "Page {{page}}, current" },
3066
+ /** `{{firstName}}` for an anonymous buyer — "Welcome, guest!" rather than "Welcome, !" (REB-24134 follow-up). */
3067
+ guest: { en: "guest" },
3059
3068
  loadingOptions: { en: "Loading subscription options" },
3060
3069
  nextPage: { en: "Next" },
3061
3070
  offerDialog: { en: "Offer" },
@@ -3070,6 +3079,7 @@ var UI_LABELS = {
3070
3079
  var localized = (fallback) => import_zod30.z.record(import_zod30.z.string(), import_zod30.z.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
3071
3080
  var CABUILabels = import_zod30.z.object({
3072
3081
  currentPage: localized(UI_LABELS.currentPage),
3082
+ guest: localized(UI_LABELS.guest),
3073
3083
  loadingOptions: localized(UI_LABELS.loadingOptions),
3074
3084
  nextPage: localized(UI_LABELS.nextPage),
3075
3085
  offerDialog: localized(UI_LABELS.offerDialog),
@@ -3080,6 +3090,7 @@ var CABUILabels = import_zod30.z.object({
3080
3090
  updating: localized(UI_LABELS.updating)
3081
3091
  }).default(() => ({
3082
3092
  currentPage: { ...UI_LABELS.currentPage },
3093
+ guest: { ...UI_LABELS.guest },
3083
3094
  loadingOptions: { ...UI_LABELS.loadingOptions },
3084
3095
  nextPage: { ...UI_LABELS.nextPage },
3085
3096
  offerDialog: { ...UI_LABELS.offerDialog },
@@ -4008,7 +4019,7 @@ var normalizeTokens = (text, knownTokens = DEFAULT_KNOWN_TOKENS) => {
4008
4019
 
4009
4020
  // src/transforms/contentBlockV1/convertContentBlockTextToV2.ts
4010
4021
  var literalText = (_field, value) => normalizeTokens(value);
4011
- var convertContentBlockTextToV2 = (language, text = literalText) => {
4022
+ var convertContentBlockTextToV2 = (language, text = literalText, textAlign = "center") => {
4012
4023
  const description = language?.description;
4013
4024
  const superTitle = language?.superTitle;
4014
4025
  const title = language?.title;
@@ -4020,20 +4031,20 @@ var convertContentBlockTextToV2 = (language, text = literalText) => {
4020
4031
  fontSize: "extraLarge",
4021
4032
  marks: [{ type: "bold" }],
4022
4033
  text: text("superTitle", superTitle),
4023
- textAlign: "center"
4034
+ textAlign
4024
4035
  }) : null,
4025
4036
  title ? convertTextToTiptapParagraph({
4026
4037
  color: "base",
4027
4038
  fontSize: "medium",
4028
4039
  marks: [{ type: "bold" }],
4029
4040
  text: text("title", title),
4030
- textAlign: "center"
4041
+ textAlign
4031
4042
  }) : null,
4032
4043
  description ? convertTextToTiptapParagraph({
4033
4044
  color: "base",
4034
4045
  fontSize: "base",
4035
4046
  text: text("description", description),
4036
- textAlign: "center"
4047
+ textAlign
4037
4048
  }) : null
4038
4049
  ].filter((p) => p !== null),
4039
4050
  type: "doc"
@@ -4505,26 +4516,28 @@ var buildStyledText = (token, style, fontSize = style?.textSize ?? "base") => {
4505
4516
  if (style?.textEmphasis === "italic") marks.push({ type: "italic" });
4506
4517
  return { content: [{ content: [{ marks, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
4507
4518
  };
4508
- var buildPriceContent = (settings) => {
4509
- const content = [
4519
+ var buildPriceContent = () => ({
4520
+ content: [
4510
4521
  {
4511
- marks: [{ attrs: { color: "accent", fontSize: "base" }, type: "textStyle" }],
4512
- text: "{{variantPrice}}",
4513
- type: "text"
4522
+ content: [
4523
+ /** Legacy renders the price in the checkout's brand color (`<Text appearance="accent">`). */
4524
+ {
4525
+ marks: [{ attrs: { color: "accent", fontSize: "base" }, type: "textStyle" }],
4526
+ text: "{{variantPrice}}",
4527
+ type: "text"
4528
+ },
4529
+ { text: " ", type: "text" },
4530
+ {
4531
+ marks: [{ type: "strike" }, { attrs: { color: "subdued" }, type: "textStyle" }],
4532
+ text: "{{variantCompareAtPrice}}",
4533
+ type: "text"
4534
+ }
4535
+ ],
4536
+ type: "paragraph"
4514
4537
  }
4515
- ];
4516
- if (settings.discount?.showSavingAmount !== false) {
4517
- content.push(
4518
- { text: " ", type: "text" },
4519
- {
4520
- marks: [{ type: "strike" }, { attrs: { color: "subdued" }, type: "textStyle" }],
4521
- text: "{{variantCompareAtPrice}}",
4522
- type: "text"
4523
- }
4524
- );
4525
- }
4526
- return { content: [{ content, type: "paragraph" }], type: "doc" };
4527
- };
4538
+ ],
4539
+ type: "doc"
4540
+ });
4528
4541
  var buildReviews = (settings) => {
4529
4542
  if (!settings.integrations || !Object.values(settings.integrations).some(Boolean)) return [];
4530
4543
  const reviews = settings.displaySettings?.reviews;
@@ -4566,8 +4579,8 @@ var buildTitle = (settings) => ({
4566
4579
  },
4567
4580
  sectionType: "text"
4568
4581
  });
4569
- var buildPrice = (settings) => ({
4570
- content: { en: buildPriceContent(settings) },
4582
+ var buildPrice = () => ({
4583
+ content: { en: buildPriceContent() },
4571
4584
  sectionType: "text"
4572
4585
  });
4573
4586
  var buildVariantTitle = (settings) => {
@@ -4680,37 +4693,23 @@ var buildOfferCard = (settings, horizontal) => {
4680
4693
  const image = buildImage(settings);
4681
4694
  const title = buildTitle(settings);
4682
4695
  const variantTitle = buildVariantTitle(settings);
4683
- const price = buildPrice(settings);
4696
+ const price = buildPrice();
4684
4697
  const description = buildDescription(settings);
4685
4698
  const reviews = buildReviews(settings);
4686
4699
  const variants = buildVariants(settings);
4687
4700
  const quantity = buildQuantity(settings);
4688
4701
  const subscription = buildSubscriptionButton(settings);
4689
4702
  const addButton = buildAddButton(settings);
4690
- if (!horizontal) {
4691
- return [
4692
- gridCardImage(image),
4693
- title,
4694
- ...variantTitle,
4695
- ...reviews,
4696
- price,
4697
- ...description,
4698
- ...variants,
4699
- ...quantity,
4700
- ...subscription,
4701
- addButton
4702
- ];
4703
- }
4704
- const info = rowsLayout([title, ...variantTitle, ...reviews, price, ...description, ...variants]);
4705
- const actions = [...subscription, addButton];
4706
- const actionsCell = actions.length === 1 ? actions[0] : rowsLayout(actions);
4703
+ const controls = [...description, ...quantity, ...variants, ...subscription];
4704
+ if (!horizontal) return [gridCardImage(image), title, ...variantTitle, ...reviews, price, ...controls, addButton];
4705
+ const info = rowsLayout([title, ...variantTitle, ...reviews, price]);
4707
4706
  const card = {
4708
4707
  direction: "grid",
4709
4708
  grid: { columns: [COMPACT_CARD_IMAGE_PX, "fill", "auto"], rows: ["auto"] },
4710
- sections: [image, info, actionsCell],
4709
+ sections: [image, info, addButton],
4711
4710
  sectionType: "layout"
4712
4711
  };
4713
- return [card, ...quantity];
4712
+ return [card, ...controls];
4714
4713
  };
4715
4714
 
4716
4715
  // src/transforms/offerV1/convertOfferToV2.ts
@@ -4750,6 +4749,19 @@ var headerVariables = (header) => HEADER_FIELDS.flatMap((field) => {
4750
4749
  const defaultValue = header[field];
4751
4750
  return defaultValue === void 0 ? [] : [{ defaultValue, name: field, type: VariableType.text }];
4752
4751
  });
4752
+ var headerNode = (header, textAlign) => ({
4753
+ content: { en: convertContentBlockTextToV2(header, headerText, textAlign) },
4754
+ sectionType: "text"
4755
+ });
4756
+ var buildHeaderNavRow = (header) => ({
4757
+ alignment: { horizontal: "start", vertical: "bottom" },
4758
+ direction: "grid",
4759
+ grid: { columns: ["fill", "auto"] },
4760
+ name: "header",
4761
+ sections: [headerNode(header, "start"), buildCarouselNav()],
4762
+ sectionType: "layout",
4763
+ spacing: "base"
4764
+ });
4753
4765
  var HAS_PRODUCTS = "hasProducts";
4754
4766
  var hasProductsMutators = () => [
4755
4767
  {
@@ -4842,6 +4854,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4842
4854
  const pageSize = Math.max(columns, 1);
4843
4855
  const limit = settings.limit ?? void 0;
4844
4856
  const showsNav = !!layout?.carousel && !paginationOff(layout.showPaginations) && (limit === void 0 || limit > pageSize);
4857
+ const headerInChrome = showsNav && hasHeaderText(header);
4845
4858
  const fitsOneRow = limit !== void 0 && limit <= pageSize;
4846
4859
  const sideBySide = direction === "grid" || direction === "columns";
4847
4860
  const offersDirection = sideBySide && (showsNav || fitsOneRow) ? "horizontal" : "vertical";
@@ -4878,6 +4891,12 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4878
4891
  */
4879
4892
  alignment: horizontalCard ? { horizontal: "start", vertical: "middle" } : { horizontal: "center", vertical: "top" },
4880
4893
  border: gridChrome ? { ...containerBorder, style: "none" } : containerBorder,
4894
+ /**
4895
+ * Legacy `OffersContext.showDivider`: a `<Divider />` between products whenever the per-card
4896
+ * border is off and the widget isn't the grid carousel (whose chrome sits on the wrapper). The
4897
+ * renderer draws it only between vertically-stacked cards (REB-24265).
4898
+ */
4899
+ ...!gridChrome && containerBorder.style === "none" && { divider: true },
4881
4900
  mutators: hasProductsMutators(),
4882
4901
  padding: gridChrome ? "none" : paddingFor(containerBorder.style),
4883
4902
  sections: [
@@ -4899,7 +4918,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4899
4918
  itemsAtOnce: Math.max(showsNav ? columns : limit ?? ENGINE_LIMIT_CEILING, 1),
4900
4919
  ...listLayout,
4901
4920
  padding: gridChrome ? paddingFor(containerBorder.style) : "none",
4902
- sections: showsNav ? [buildCarouselNav(), offers] : [offers],
4921
+ sections: showsNav ? [headerInChrome ? buildHeaderNavRow(header) : buildCarouselNav(), offers] : [offers],
4903
4922
  sectionType: "carousel"
4904
4923
  };
4905
4924
  return CABRootSection.parse({
@@ -4909,10 +4928,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4909
4928
  // The widget name is required by the admin save schema; carry the legacy widget's name through.
4910
4929
  ...name && { name },
4911
4930
  previewMode: settings.previewMode,
4912
- sections: [
4913
- ...hasHeaderText(header) ? [{ content: { en: convertContentBlockTextToV2(header, headerText) }, sectionType: "text" }] : [],
4914
- display
4915
- ],
4931
+ sections: [...hasHeaderText(header) && !headerInChrome ? [headerNode(header, "center")] : [], display],
4916
4932
  // CABTracking's schema fallbacks fill missing or null fields and the missing object; malformed values throw.
4917
4933
  tracking: settings.tracking,
4918
4934
  type: SHOPIFY_CHECKOUT_EXTENSION,
package/dist/index.mjs CHANGED
@@ -2221,6 +2221,13 @@ var CABProductsSection = z18.object({
2221
2221
  // src/schema/widgets/checkout-and-beyond/offers.ts
2222
2222
  var CABOffersSection = z19.lazy(
2223
2223
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
2224
+ /**
2225
+ * A rule between consecutive cards in the vertical list — legacy checkout-offers' `<Divider />`,
2226
+ * which it drew whenever the per-card border was off (a borderless stack otherwise reads as one
2227
+ * run of products). Optional, not defaulted: only the v1 converter sets it (REB-24265); a
2228
+ * hand-built tree keeps React CAB's dividerless rendering.
2229
+ */
2230
+ divider: z19.boolean().optional(),
2224
2231
  sections: z19.union([z19.array(z19.lazy(() => CABSection)), z19.strictObject({}).transform(() => [])]).default(() => [
2225
2232
  CABBannerSection.parse({
2226
2233
  buttonField: "undoAddToOrder",
@@ -2770,6 +2777,8 @@ var CABLayoutSection = z29.object({
2770
2777
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
2771
2778
  var UI_LABELS = {
2772
2779
  currentPage: { en: "Page {{page}}, current" },
2780
+ /** `{{firstName}}` for an anonymous buyer — "Welcome, guest!" rather than "Welcome, !" (REB-24134 follow-up). */
2781
+ guest: { en: "guest" },
2773
2782
  loadingOptions: { en: "Loading subscription options" },
2774
2783
  nextPage: { en: "Next" },
2775
2784
  offerDialog: { en: "Offer" },
@@ -2784,6 +2793,7 @@ var UI_LABELS = {
2784
2793
  var localized = (fallback) => z30.record(z30.string(), z30.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
2785
2794
  var CABUILabels = z30.object({
2786
2795
  currentPage: localized(UI_LABELS.currentPage),
2796
+ guest: localized(UI_LABELS.guest),
2787
2797
  loadingOptions: localized(UI_LABELS.loadingOptions),
2788
2798
  nextPage: localized(UI_LABELS.nextPage),
2789
2799
  offerDialog: localized(UI_LABELS.offerDialog),
@@ -2794,6 +2804,7 @@ var CABUILabels = z30.object({
2794
2804
  updating: localized(UI_LABELS.updating)
2795
2805
  }).default(() => ({
2796
2806
  currentPage: { ...UI_LABELS.currentPage },
2807
+ guest: { ...UI_LABELS.guest },
2797
2808
  loadingOptions: { ...UI_LABELS.loadingOptions },
2798
2809
  nextPage: { ...UI_LABELS.nextPage },
2799
2810
  offerDialog: { ...UI_LABELS.offerDialog },
@@ -3722,7 +3733,7 @@ var normalizeTokens = (text, knownTokens = DEFAULT_KNOWN_TOKENS) => {
3722
3733
 
3723
3734
  // src/transforms/contentBlockV1/convertContentBlockTextToV2.ts
3724
3735
  var literalText = (_field, value) => normalizeTokens(value);
3725
- var convertContentBlockTextToV2 = (language, text = literalText) => {
3736
+ var convertContentBlockTextToV2 = (language, text = literalText, textAlign = "center") => {
3726
3737
  const description = language?.description;
3727
3738
  const superTitle = language?.superTitle;
3728
3739
  const title = language?.title;
@@ -3734,20 +3745,20 @@ var convertContentBlockTextToV2 = (language, text = literalText) => {
3734
3745
  fontSize: "extraLarge",
3735
3746
  marks: [{ type: "bold" }],
3736
3747
  text: text("superTitle", superTitle),
3737
- textAlign: "center"
3748
+ textAlign
3738
3749
  }) : null,
3739
3750
  title ? convertTextToTiptapParagraph({
3740
3751
  color: "base",
3741
3752
  fontSize: "medium",
3742
3753
  marks: [{ type: "bold" }],
3743
3754
  text: text("title", title),
3744
- textAlign: "center"
3755
+ textAlign
3745
3756
  }) : null,
3746
3757
  description ? convertTextToTiptapParagraph({
3747
3758
  color: "base",
3748
3759
  fontSize: "base",
3749
3760
  text: text("description", description),
3750
- textAlign: "center"
3761
+ textAlign
3751
3762
  }) : null
3752
3763
  ].filter((p) => p !== null),
3753
3764
  type: "doc"
@@ -4219,26 +4230,28 @@ var buildStyledText = (token, style, fontSize = style?.textSize ?? "base") => {
4219
4230
  if (style?.textEmphasis === "italic") marks.push({ type: "italic" });
4220
4231
  return { content: [{ content: [{ marks, text: token, type: "text" }], type: "paragraph" }], type: "doc" };
4221
4232
  };
4222
- var buildPriceContent = (settings) => {
4223
- const content = [
4233
+ var buildPriceContent = () => ({
4234
+ content: [
4224
4235
  {
4225
- marks: [{ attrs: { color: "accent", fontSize: "base" }, type: "textStyle" }],
4226
- text: "{{variantPrice}}",
4227
- type: "text"
4236
+ content: [
4237
+ /** Legacy renders the price in the checkout's brand color (`<Text appearance="accent">`). */
4238
+ {
4239
+ marks: [{ attrs: { color: "accent", fontSize: "base" }, type: "textStyle" }],
4240
+ text: "{{variantPrice}}",
4241
+ type: "text"
4242
+ },
4243
+ { text: " ", type: "text" },
4244
+ {
4245
+ marks: [{ type: "strike" }, { attrs: { color: "subdued" }, type: "textStyle" }],
4246
+ text: "{{variantCompareAtPrice}}",
4247
+ type: "text"
4248
+ }
4249
+ ],
4250
+ type: "paragraph"
4228
4251
  }
4229
- ];
4230
- if (settings.discount?.showSavingAmount !== false) {
4231
- content.push(
4232
- { text: " ", type: "text" },
4233
- {
4234
- marks: [{ type: "strike" }, { attrs: { color: "subdued" }, type: "textStyle" }],
4235
- text: "{{variantCompareAtPrice}}",
4236
- type: "text"
4237
- }
4238
- );
4239
- }
4240
- return { content: [{ content, type: "paragraph" }], type: "doc" };
4241
- };
4252
+ ],
4253
+ type: "doc"
4254
+ });
4242
4255
  var buildReviews = (settings) => {
4243
4256
  if (!settings.integrations || !Object.values(settings.integrations).some(Boolean)) return [];
4244
4257
  const reviews = settings.displaySettings?.reviews;
@@ -4280,8 +4293,8 @@ var buildTitle = (settings) => ({
4280
4293
  },
4281
4294
  sectionType: "text"
4282
4295
  });
4283
- var buildPrice = (settings) => ({
4284
- content: { en: buildPriceContent(settings) },
4296
+ var buildPrice = () => ({
4297
+ content: { en: buildPriceContent() },
4285
4298
  sectionType: "text"
4286
4299
  });
4287
4300
  var buildVariantTitle = (settings) => {
@@ -4394,37 +4407,23 @@ var buildOfferCard = (settings, horizontal) => {
4394
4407
  const image = buildImage(settings);
4395
4408
  const title = buildTitle(settings);
4396
4409
  const variantTitle = buildVariantTitle(settings);
4397
- const price = buildPrice(settings);
4410
+ const price = buildPrice();
4398
4411
  const description = buildDescription(settings);
4399
4412
  const reviews = buildReviews(settings);
4400
4413
  const variants = buildVariants(settings);
4401
4414
  const quantity = buildQuantity(settings);
4402
4415
  const subscription = buildSubscriptionButton(settings);
4403
4416
  const addButton = buildAddButton(settings);
4404
- if (!horizontal) {
4405
- return [
4406
- gridCardImage(image),
4407
- title,
4408
- ...variantTitle,
4409
- ...reviews,
4410
- price,
4411
- ...description,
4412
- ...variants,
4413
- ...quantity,
4414
- ...subscription,
4415
- addButton
4416
- ];
4417
- }
4418
- const info = rowsLayout([title, ...variantTitle, ...reviews, price, ...description, ...variants]);
4419
- const actions = [...subscription, addButton];
4420
- const actionsCell = actions.length === 1 ? actions[0] : rowsLayout(actions);
4417
+ const controls = [...description, ...quantity, ...variants, ...subscription];
4418
+ if (!horizontal) return [gridCardImage(image), title, ...variantTitle, ...reviews, price, ...controls, addButton];
4419
+ const info = rowsLayout([title, ...variantTitle, ...reviews, price]);
4421
4420
  const card = {
4422
4421
  direction: "grid",
4423
4422
  grid: { columns: [COMPACT_CARD_IMAGE_PX, "fill", "auto"], rows: ["auto"] },
4424
- sections: [image, info, actionsCell],
4423
+ sections: [image, info, addButton],
4425
4424
  sectionType: "layout"
4426
4425
  };
4427
- return [card, ...quantity];
4426
+ return [card, ...controls];
4428
4427
  };
4429
4428
 
4430
4429
  // src/transforms/offerV1/convertOfferToV2.ts
@@ -4464,6 +4463,19 @@ var headerVariables = (header) => HEADER_FIELDS.flatMap((field) => {
4464
4463
  const defaultValue = header[field];
4465
4464
  return defaultValue === void 0 ? [] : [{ defaultValue, name: field, type: VariableType.text }];
4466
4465
  });
4466
+ var headerNode = (header, textAlign) => ({
4467
+ content: { en: convertContentBlockTextToV2(header, headerText, textAlign) },
4468
+ sectionType: "text"
4469
+ });
4470
+ var buildHeaderNavRow = (header) => ({
4471
+ alignment: { horizontal: "start", vertical: "bottom" },
4472
+ direction: "grid",
4473
+ grid: { columns: ["fill", "auto"] },
4474
+ name: "header",
4475
+ sections: [headerNode(header, "start"), buildCarouselNav()],
4476
+ sectionType: "layout",
4477
+ spacing: "base"
4478
+ });
4467
4479
  var HAS_PRODUCTS = "hasProducts";
4468
4480
  var hasProductsMutators = () => [
4469
4481
  {
@@ -4556,6 +4568,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4556
4568
  const pageSize = Math.max(columns, 1);
4557
4569
  const limit = settings.limit ?? void 0;
4558
4570
  const showsNav = !!layout?.carousel && !paginationOff(layout.showPaginations) && (limit === void 0 || limit > pageSize);
4571
+ const headerInChrome = showsNav && hasHeaderText(header);
4559
4572
  const fitsOneRow = limit !== void 0 && limit <= pageSize;
4560
4573
  const sideBySide = direction === "grid" || direction === "columns";
4561
4574
  const offersDirection = sideBySide && (showsNav || fitsOneRow) ? "horizontal" : "vertical";
@@ -4592,6 +4605,12 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4592
4605
  */
4593
4606
  alignment: horizontalCard ? { horizontal: "start", vertical: "middle" } : { horizontal: "center", vertical: "top" },
4594
4607
  border: gridChrome ? { ...containerBorder, style: "none" } : containerBorder,
4608
+ /**
4609
+ * Legacy `OffersContext.showDivider`: a `<Divider />` between products whenever the per-card
4610
+ * border is off and the widget isn't the grid carousel (whose chrome sits on the wrapper). The
4611
+ * renderer draws it only between vertically-stacked cards (REB-24265).
4612
+ */
4613
+ ...!gridChrome && containerBorder.style === "none" && { divider: true },
4595
4614
  mutators: hasProductsMutators(),
4596
4615
  padding: gridChrome ? "none" : paddingFor(containerBorder.style),
4597
4616
  sections: [
@@ -4613,7 +4632,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4613
4632
  itemsAtOnce: Math.max(showsNav ? columns : limit ?? ENGINE_LIMIT_CEILING, 1),
4614
4633
  ...listLayout,
4615
4634
  padding: gridChrome ? paddingFor(containerBorder.style) : "none",
4616
- sections: showsNav ? [buildCarouselNav(), offers] : [offers],
4635
+ sections: showsNav ? [headerInChrome ? buildHeaderNavRow(header) : buildCarouselNav(), offers] : [offers],
4617
4636
  sectionType: "carousel"
4618
4637
  };
4619
4638
  return CABRootSection.parse({
@@ -4623,10 +4642,7 @@ var convertOfferToV2 = ({ id, name, settings }) => {
4623
4642
  // The widget name is required by the admin save schema; carry the legacy widget's name through.
4624
4643
  ...name && { name },
4625
4644
  previewMode: settings.previewMode,
4626
- sections: [
4627
- ...hasHeaderText(header) ? [{ content: { en: convertContentBlockTextToV2(header, headerText) }, sectionType: "text" }] : [],
4628
- display
4629
- ],
4645
+ sections: [...hasHeaderText(header) && !headerInChrome ? [headerNode(header, "center")] : [], display],
4630
4646
  // CABTracking's schema fallbacks fill missing or null fields and the missing object; malformed values throw.
4631
4647
  tracking: settings.tracking,
4632
4648
  type: SHOPIFY_CHECKOUT_EXTENSION,
@@ -1048,6 +1048,13 @@ var CABProductsSection = import_zod8.z.object({
1048
1048
  // src/schema/widgets/checkout-and-beyond/offers.ts
1049
1049
  var CABOffersSection = import_zod9.z.lazy(
1050
1050
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
1051
+ /**
1052
+ * A rule between consecutive cards in the vertical list — legacy checkout-offers' `<Divider />`,
1053
+ * which it drew whenever the per-card border was off (a borderless stack otherwise reads as one
1054
+ * run of products). Optional, not defaulted: only the v1 converter sets it (REB-24265); a
1055
+ * hand-built tree keeps React CAB's dividerless rendering.
1056
+ */
1057
+ divider: import_zod9.z.boolean().optional(),
1051
1058
  sections: import_zod9.z.union([import_zod9.z.array(import_zod9.z.lazy(() => CABSection)), import_zod9.z.strictObject({}).transform(() => [])]).default(() => [
1052
1059
  CABBannerSection.parse({
1053
1060
  buttonField: "undoAddToOrder",
@@ -1826,6 +1833,8 @@ var import_zod21 = require("zod");
1826
1833
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
1827
1834
  var UI_LABELS = {
1828
1835
  currentPage: { en: "Page {{page}}, current" },
1836
+ /** `{{firstName}}` for an anonymous buyer — "Welcome, guest!" rather than "Welcome, !" (REB-24134 follow-up). */
1837
+ guest: { en: "guest" },
1829
1838
  loadingOptions: { en: "Loading subscription options" },
1830
1839
  nextPage: { en: "Next" },
1831
1840
  offerDialog: { en: "Offer" },
@@ -1840,6 +1849,7 @@ var UI_LABELS = {
1840
1849
  var localized = (fallback) => import_zod21.z.record(import_zod21.z.string(), import_zod21.z.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1841
1850
  var CABUILabels = import_zod21.z.object({
1842
1851
  currentPage: localized(UI_LABELS.currentPage),
1852
+ guest: localized(UI_LABELS.guest),
1843
1853
  loadingOptions: localized(UI_LABELS.loadingOptions),
1844
1854
  nextPage: localized(UI_LABELS.nextPage),
1845
1855
  offerDialog: localized(UI_LABELS.offerDialog),
@@ -1850,6 +1860,7 @@ var CABUILabels = import_zod21.z.object({
1850
1860
  updating: localized(UI_LABELS.updating)
1851
1861
  }).default(() => ({
1852
1862
  currentPage: { ...UI_LABELS.currentPage },
1863
+ guest: { ...UI_LABELS.guest },
1853
1864
  loadingOptions: { ...UI_LABELS.loadingOptions },
1854
1865
  nextPage: { ...UI_LABELS.nextPage },
1855
1866
  offerDialog: { ...UI_LABELS.offerDialog },
@@ -851,6 +851,13 @@ var CABProductsSection = z8.object({
851
851
  // src/schema/widgets/checkout-and-beyond/offers.ts
852
852
  var CABOffersSection = z9.lazy(
853
853
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
854
+ /**
855
+ * A rule between consecutive cards in the vertical list — legacy checkout-offers' `<Divider />`,
856
+ * which it drew whenever the per-card border was off (a borderless stack otherwise reads as one
857
+ * run of products). Optional, not defaulted: only the v1 converter sets it (REB-24265); a
858
+ * hand-built tree keeps React CAB's dividerless rendering.
859
+ */
860
+ divider: z9.boolean().optional(),
854
861
  sections: z9.union([z9.array(z9.lazy(() => CABSection)), z9.strictObject({}).transform(() => [])]).default(() => [
855
862
  CABBannerSection.parse({
856
863
  buttonField: "undoAddToOrder",
@@ -1629,6 +1636,8 @@ import { z as z21 } from "zod";
1629
1636
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
1630
1637
  var UI_LABELS = {
1631
1638
  currentPage: { en: "Page {{page}}, current" },
1639
+ /** `{{firstName}}` for an anonymous buyer — "Welcome, guest!" rather than "Welcome, !" (REB-24134 follow-up). */
1640
+ guest: { en: "guest" },
1632
1641
  loadingOptions: { en: "Loading subscription options" },
1633
1642
  nextPage: { en: "Next" },
1634
1643
  offerDialog: { en: "Offer" },
@@ -1643,6 +1652,7 @@ var UI_LABELS = {
1643
1652
  var localized = (fallback) => z21.record(z21.string(), z21.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1644
1653
  var CABUILabels = z21.object({
1645
1654
  currentPage: localized(UI_LABELS.currentPage),
1655
+ guest: localized(UI_LABELS.guest),
1646
1656
  loadingOptions: localized(UI_LABELS.loadingOptions),
1647
1657
  nextPage: localized(UI_LABELS.nextPage),
1648
1658
  offerDialog: localized(UI_LABELS.offerDialog),
@@ -1653,6 +1663,7 @@ var CABUILabels = z21.object({
1653
1663
  updating: localized(UI_LABELS.updating)
1654
1664
  }).default(() => ({
1655
1665
  currentPage: { ...UI_LABELS.currentPage },
1666
+ guest: { ...UI_LABELS.guest },
1656
1667
  loadingOptions: { ...UI_LABELS.loadingOptions },
1657
1668
  nextPage: { ...UI_LABELS.nextPage },
1658
1669
  offerDialog: { ...UI_LABELS.offerDialog },
@@ -889,6 +889,13 @@ var CABProductsSection = import_zod11.z.object({
889
889
  // src/schema/widgets/checkout-and-beyond/offers.ts
890
890
  var CABOffersSection = import_zod12.z.lazy(
891
891
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
892
+ /**
893
+ * A rule between consecutive cards in the vertical list — legacy checkout-offers' `<Divider />`,
894
+ * which it drew whenever the per-card border was off (a borderless stack otherwise reads as one
895
+ * run of products). Optional, not defaulted: only the v1 converter sets it (REB-24265); a
896
+ * hand-built tree keeps React CAB's dividerless rendering.
897
+ */
898
+ divider: import_zod12.z.boolean().optional(),
892
899
  sections: import_zod12.z.union([import_zod12.z.array(import_zod12.z.lazy(() => CABSection)), import_zod12.z.strictObject({}).transform(() => [])]).default(() => [
893
900
  CABBannerSection.parse({
894
901
  buttonField: "undoAddToOrder",
@@ -1438,6 +1445,8 @@ var CABLayoutSection = import_zod22.z.object({
1438
1445
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
1439
1446
  var UI_LABELS = {
1440
1447
  currentPage: { en: "Page {{page}}, current" },
1448
+ /** `{{firstName}}` for an anonymous buyer — "Welcome, guest!" rather than "Welcome, !" (REB-24134 follow-up). */
1449
+ guest: { en: "guest" },
1441
1450
  loadingOptions: { en: "Loading subscription options" },
1442
1451
  nextPage: { en: "Next" },
1443
1452
  offerDialog: { en: "Offer" },
@@ -1452,6 +1461,7 @@ var UI_LABELS = {
1452
1461
  var localized = (fallback) => import_zod23.z.record(import_zod23.z.string(), import_zod23.z.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1453
1462
  var CABUILabels = import_zod23.z.object({
1454
1463
  currentPage: localized(UI_LABELS.currentPage),
1464
+ guest: localized(UI_LABELS.guest),
1455
1465
  loadingOptions: localized(UI_LABELS.loadingOptions),
1456
1466
  nextPage: localized(UI_LABELS.nextPage),
1457
1467
  offerDialog: localized(UI_LABELS.offerDialog),
@@ -1462,6 +1472,7 @@ var CABUILabels = import_zod23.z.object({
1462
1472
  updating: localized(UI_LABELS.updating)
1463
1473
  }).default(() => ({
1464
1474
  currentPage: { ...UI_LABELS.currentPage },
1475
+ guest: { ...UI_LABELS.guest },
1465
1476
  loadingOptions: { ...UI_LABELS.loadingOptions },
1466
1477
  nextPage: { ...UI_LABELS.nextPage },
1467
1478
  offerDialog: { ...UI_LABELS.offerDialog },
@@ -864,6 +864,13 @@ var CABProductsSection = z11.object({
864
864
  // src/schema/widgets/checkout-and-beyond/offers.ts
865
865
  var CABOffersSection = z12.lazy(
866
866
  () => CABLayoutSection.omit({ sections: true, sectionType: true }).extend({
867
+ /**
868
+ * A rule between consecutive cards in the vertical list — legacy checkout-offers' `<Divider />`,
869
+ * which it drew whenever the per-card border was off (a borderless stack otherwise reads as one
870
+ * run of products). Optional, not defaulted: only the v1 converter sets it (REB-24265); a
871
+ * hand-built tree keeps React CAB's dividerless rendering.
872
+ */
873
+ divider: z12.boolean().optional(),
867
874
  sections: z12.union([z12.array(z12.lazy(() => CABSection)), z12.strictObject({}).transform(() => [])]).default(() => [
868
875
  CABBannerSection.parse({
869
876
  buttonField: "undoAddToOrder",
@@ -1413,6 +1420,8 @@ var CABLayoutSection = z22.object({
1413
1420
  // src/schema/widgets/checkout-and-beyond/uiLabels.ts
1414
1421
  var UI_LABELS = {
1415
1422
  currentPage: { en: "Page {{page}}, current" },
1423
+ /** `{{firstName}}` for an anonymous buyer — "Welcome, guest!" rather than "Welcome, !" (REB-24134 follow-up). */
1424
+ guest: { en: "guest" },
1416
1425
  loadingOptions: { en: "Loading subscription options" },
1417
1426
  nextPage: { en: "Next" },
1418
1427
  offerDialog: { en: "Offer" },
@@ -1427,6 +1436,7 @@ var UI_LABELS = {
1427
1436
  var localized = (fallback) => z23.record(z23.string(), z23.string()).default(() => ({ ...fallback })).transform((labels) => Object.keys(labels).length > 0 ? labels : { ...fallback });
1428
1437
  var CABUILabels = z23.object({
1429
1438
  currentPage: localized(UI_LABELS.currentPage),
1439
+ guest: localized(UI_LABELS.guest),
1430
1440
  loadingOptions: localized(UI_LABELS.loadingOptions),
1431
1441
  nextPage: localized(UI_LABELS.nextPage),
1432
1442
  offerDialog: localized(UI_LABELS.offerDialog),
@@ -1437,6 +1447,7 @@ var CABUILabels = z23.object({
1437
1447
  updating: localized(UI_LABELS.updating)
1438
1448
  }).default(() => ({
1439
1449
  currentPage: { ...UI_LABELS.currentPage },
1450
+ guest: { ...UI_LABELS.guest },
1440
1451
  loadingOptions: { ...UI_LABELS.loadingOptions },
1441
1452
  nextPage: { ...UI_LABELS.nextPage },
1442
1453
  offerDialog: { ...UI_LABELS.offerDialog },
@@ -361,6 +361,7 @@ export declare const WidgetData: z.ZodDiscriminatedUnion<[z.ZodObject<{
361
361
  } | null | undefined>>;
362
362
  uiLabels: z.ZodDefault<z.ZodObject<{
363
363
  currentPage: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
364
+ guest: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
364
365
  loadingOptions: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
365
366
  nextPage: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
366
367
  offerDialog: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
@@ -711,6 +712,7 @@ export declare const WidgetData: z.ZodDiscriminatedUnion<[z.ZodObject<{
711
712
  } | null | undefined>>;
712
713
  uiLabels: z.ZodDefault<z.ZodObject<{
713
714
  currentPage: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
715
+ guest: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
714
716
  loadingOptions: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
715
717
  nextPage: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
716
718
  offerDialog: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
@@ -1038,6 +1040,7 @@ export declare const WidgetData: z.ZodDiscriminatedUnion<[z.ZodObject<{
1038
1040
  } | null | undefined>>;
1039
1041
  uiLabels: z.ZodDefault<z.ZodObject<{
1040
1042
  currentPage: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
1043
+ guest: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
1041
1044
  loadingOptions: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
1042
1045
  nextPage: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
1043
1046
  offerDialog: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodTransform<Record<string, string>, Record<string, string>>>;
@@ -267,10 +267,12 @@ export declare const CABOffersSection: z.ZodLazy<z.ZodObject<{
267
267
  extraLoose: "extraLoose";
268
268
  }>>;
269
269
  viewUrl: z.ZodOptional<z.ZodString>;
270
+ divider: z.ZodOptional<z.ZodBoolean>;
270
271
  sections: z.ZodDefault<z.ZodUnion<readonly [z.ZodArray<z.ZodLazy<z.ZodType<CABSection, unknown, z.core.$ZodTypeInternals<CABSection, unknown>>>>, z.ZodPipe<z.ZodObject<{}, z.core.$strict>, z.ZodTransform<never[], Record<string, never>>>]>>;
271
272
  sectionType: z.ZodDefault<z.ZodLiteral<"offers">>;
272
273
  }, z.core.$strip>>;
273
274
  export type CABOffersSection = Omit<CABLayoutSection, 'sectionType'> & {
275
+ divider?: boolean;
274
276
  sectionType: 'offers';
275
277
  };
276
278
  export type CABOffersSectionProps = CABOffersSection & SectionDetails;