@reblu/site-blocks 0.28.0 → 0.29.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
@@ -26,13 +26,19 @@ __export(src_exports, {
26
26
  CartAdjustmentsNotice: () => CartAdjustmentsNotice,
27
27
  CartLineList: () => CartLineList,
28
28
  CartSummary: () => CartSummary,
29
+ CheckoutDeliveryChoice: () => CheckoutDeliveryChoice,
29
30
  CheckoutForm: () => CheckoutForm,
30
31
  CheckoutLoginPrompt: () => CheckoutLoginPrompt,
32
+ CheckoutPayAction: () => CheckoutPayAction,
33
+ CheckoutQuoteSummary: () => CheckoutQuoteSummary,
34
+ CheckoutTermsAcceptance: () => CheckoutTermsAcceptance,
31
35
  ContactInterestField: () => ContactInterestField,
32
36
  CourseCatalogFilters: () => CourseCatalogFilters,
33
37
  CourseDescription: () => CourseDescription,
34
38
  CoursePurchaseTerms: () => CoursePurchaseTerms,
35
39
  DATA_REQUEST_TYPES: () => import_site_contracts.DATA_REQUEST_TYPES,
40
+ DEFAULT_CHECKOUT_DELIVERY_CHOICE_LABELS: () => DEFAULT_CHECKOUT_DELIVERY_CHOICE_LABELS,
41
+ DEFAULT_CHECKOUT_QUOTE_SUMMARY_LABELS: () => DEFAULT_CHECKOUT_QUOTE_SUMMARY_LABELS,
36
42
  DEFAULT_COURSE_CATALOG_FILTERS_LABELS: () => DEFAULT_COURSE_CATALOG_FILTERS_LABELS,
37
43
  DEFAULT_COURSE_PRICE_BANDS: () => DEFAULT_COURSE_PRICE_BANDS,
38
44
  DEFAULT_COURSE_PURCHASE_TERMS_LABELS: () => DEFAULT_COURSE_PURCHASE_TERMS_LABELS,
@@ -44,6 +50,7 @@ __export(src_exports, {
44
50
  DEFAULT_TRUST_BADGE_HEADINGS: () => DEFAULT_TRUST_BADGE_HEADINGS,
45
51
  DEFAULT_TRUST_BADGE_TYPE_ORDER: () => DEFAULT_TRUST_BADGE_TYPE_ORDER,
46
52
  DEFAULT_TRUST_ICONS: () => DEFAULT_TRUST_ICONS,
53
+ EMPTY_CHECKOUT_ADDRESS: () => EMPTY_CHECKOUT_ADDRESS,
47
54
  EMPTY_FULL_INVOICE_VALUE: () => EMPTY_FULL_INVOICE_VALUE,
48
55
  FaqAccordion: () => FaqAccordion,
49
56
  FullInvoiceFields: () => FullInvoiceFields,
@@ -67,17 +74,21 @@ __export(src_exports, {
67
74
  buildFaqPageJsonLd: () => buildFaqPageJsonLd,
68
75
  buildShareUrls: () => buildShareUrls,
69
76
  collectFaqItems: () => collectFaqItems,
77
+ defaultCheckoutFulfillment: () => defaultCheckoutFulfillment,
70
78
  formatPrice: () => formatPrice,
71
79
  getShopErrorMessage: () => getShopErrorMessage,
72
80
  isAllowedYouTubeHost: () => isAllowedYouTubeHost,
73
81
  isOverSimplifiedInvoiceCap: () => isOverSimplifiedInvoiceCap,
74
82
  markdownToPlainText: () => markdownToPlainText,
75
83
  markdownToSafeHtml: () => markdownToSafeHtml,
84
+ quoteRequiresDelivery: () => quoteRequiresDelivery,
76
85
  readingTime: () => readingTime,
77
86
  sanitizeHtml: () => sanitizeHtml,
78
87
  shopIssuesInvoices: () => shopIssuesInvoices,
79
88
  shouldRenderShopFilters: () => shouldRenderShopFilters,
80
- toCheckoutInvoiceFields: () => toCheckoutInvoiceFields
89
+ toCheckoutFulfillmentFields: () => toCheckoutFulfillmentFields,
90
+ toCheckoutInvoiceFields: () => toCheckoutInvoiceFields,
91
+ toCheckoutTermsFields: () => toCheckoutTermsFields
81
92
  });
82
93
  module.exports = __toCommonJS(src_exports);
83
94
 
@@ -16175,9 +16186,399 @@ function FullInvoiceFields({
16175
16186
  ] });
16176
16187
  }
16177
16188
 
16178
- // src/components/contact-interest-field.tsx
16189
+ // src/components/checkout-delivery-choice.tsx
16179
16190
  var import_utils26 = require("@reblu/site-ui/utils");
16180
16191
  var import_jsx_runtime30 = require("react/jsx-runtime");
16192
+ var EMPTY_CHECKOUT_ADDRESS = {
16193
+ firstName: "",
16194
+ lastName: "",
16195
+ street: "",
16196
+ postalCode: "",
16197
+ city: "",
16198
+ region: ""
16199
+ };
16200
+ var DEFAULT_CHECKOUT_DELIVERY_CHOICE_LABELS = {
16201
+ legend: "Entrega",
16202
+ free: "Gratis",
16203
+ pickupPointsLegend: "Punto de recogida",
16204
+ addressLegend: "Direcci\xF3n de entrega",
16205
+ firstName: "Nombre",
16206
+ lastName: "Apellidos",
16207
+ street: "Direcci\xF3n",
16208
+ postalCode: "C\xF3digo postal",
16209
+ city: "Ciudad",
16210
+ region: "Provincia"
16211
+ };
16212
+ var INPUT_CLASS = "w-full rounded-lg border bg-background px-3 py-2 text-sm transition focus:outline-none focus:ring-2 focus:ring-primary/20";
16213
+ var ADDRESS_FIELDS = [
16214
+ { key: "firstName", autoComplete: "shipping given-name", required: true },
16215
+ { key: "lastName", autoComplete: "shipping family-name", required: true },
16216
+ { key: "street", autoComplete: "shipping street-address", required: true, wide: true },
16217
+ { key: "postalCode", autoComplete: "shipping postal-code", required: true },
16218
+ { key: "city", autoComplete: "shipping address-level2", required: true },
16219
+ { key: "region", autoComplete: "shipping address-level1", required: false }
16220
+ ];
16221
+ function pickupDescription(location2) {
16222
+ return [
16223
+ `${location2.address}, ${location2.postalCode} ${location2.city}`,
16224
+ location2.openingHoursText,
16225
+ location2.pickupReadyText
16226
+ ].filter(Boolean).join(". ");
16227
+ }
16228
+ function CheckoutDeliveryChoice({
16229
+ delivery,
16230
+ copy,
16231
+ value,
16232
+ onChange,
16233
+ address,
16234
+ onAddressChange,
16235
+ addressErrors,
16236
+ error,
16237
+ quote,
16238
+ requiresDelivery = true,
16239
+ labels,
16240
+ currencyCode,
16241
+ locale,
16242
+ id: uid = "checkout-delivery",
16243
+ className
16244
+ }) {
16245
+ const t = { ...DEFAULT_CHECKOUT_DELIVERY_CHOICE_LABELS, ...labels };
16246
+ const { homeDelivery, pickup } = delivery.methods;
16247
+ if (!requiresDelivery || !homeDelivery && !pickup) return null;
16248
+ const price = (cents) => formatPrice(cents, currencyCode, locale);
16249
+ const quotedShipping = quote?.fulfillment.type === "SHIPPING" ? quote.shipping : null;
16250
+ const homeCost = quotedShipping ? quotedShipping.isFree ? t.free : price(quotedShipping.cost) : delivery.shippingEnabled && delivery.defaultShippingCost ? price(delivery.defaultShippingCost) : t.free;
16251
+ const isPickup = value?.type === "PICKUP";
16252
+ const isShipping = value?.type === "SHIPPING";
16253
+ const errorId = `${uid}-delivery-error`;
16254
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
16255
+ "fieldset",
16256
+ {
16257
+ "data-slot": "checkout-delivery",
16258
+ "aria-describedby": error ? errorId : void 0,
16259
+ className: (0, import_utils26.cn)("space-y-4", className),
16260
+ children: [
16261
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("legend", { className: "mb-2 text-lg font-semibold", children: t.legend }),
16262
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2", children: [
16263
+ homeDelivery ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex cursor-pointer items-start gap-3 rounded-xl border border-border p-4 has-[:checked]:border-primary", children: [
16264
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16265
+ "input",
16266
+ {
16267
+ type: "radio",
16268
+ name: `${uid}-method`,
16269
+ checked: isShipping,
16270
+ onChange: () => onChange({ type: "SHIPPING" }),
16271
+ className: "mt-0.5 size-4 accent-primary"
16272
+ }
16273
+ ),
16274
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "flex-1 space-y-1", children: [
16275
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "flex justify-between gap-2 font-medium", children: [
16276
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: copy.shippingOptionLabel }),
16277
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "tabular-nums", children: homeCost })
16278
+ ] }),
16279
+ delivery.estimatedDeliveryText ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "block text-sm text-muted-foreground", children: delivery.estimatedDeliveryText }) : null
16280
+ ] })
16281
+ ] }) : null,
16282
+ pickup ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex cursor-pointer items-start gap-3 rounded-xl border border-border p-4 has-[:checked]:border-primary", children: [
16283
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16284
+ "input",
16285
+ {
16286
+ type: "radio",
16287
+ name: `${uid}-method`,
16288
+ checked: isPickup,
16289
+ onChange: () => onChange({ type: "PICKUP" }),
16290
+ className: "mt-0.5 size-4 accent-primary"
16291
+ }
16292
+ ),
16293
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "flex flex-1 justify-between gap-2 font-medium", children: [
16294
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: copy.pickupOptionLabel }),
16295
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: t.free })
16296
+ ] })
16297
+ ] }) : null
16298
+ ] }),
16299
+ error ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { id: errorId, role: "alert", className: "text-sm text-destructive", children: error }) : null,
16300
+ isPickup ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { role: "radiogroup", "aria-labelledby": `${uid}-points`, className: "space-y-2", children: [
16301
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { id: `${uid}-points`, className: "text-sm font-medium", children: t.pickupPointsLegend }),
16302
+ delivery.pickupLocations.map((location2) => {
16303
+ const descId = `${uid}-point-${location2.id}`;
16304
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
16305
+ "label",
16306
+ {
16307
+ className: "flex cursor-pointer items-start gap-3 rounded-lg border border-border p-3 has-[:checked]:border-primary",
16308
+ children: [
16309
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16310
+ "input",
16311
+ {
16312
+ type: "radio",
16313
+ name: `${uid}-point`,
16314
+ checked: value?.pickupLocationId === location2.id,
16315
+ onChange: () => onChange({ type: "PICKUP", pickupLocationId: location2.id }),
16316
+ "aria-describedby": descId,
16317
+ className: "mt-0.5 size-4 accent-primary"
16318
+ }
16319
+ ),
16320
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "space-y-0.5 text-sm", children: [
16321
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "block font-medium", children: location2.name }),
16322
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { id: descId, className: "block text-muted-foreground", children: pickupDescription(location2) })
16323
+ ] })
16324
+ ]
16325
+ },
16326
+ location2.id
16327
+ );
16328
+ })
16329
+ ] }) : null,
16330
+ isShipping ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("fieldset", { className: "space-y-3", children: [
16331
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("legend", { className: "mb-2 text-sm font-medium", children: t.addressLegend }),
16332
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: ADDRESS_FIELDS.map(({ key: key2, autoComplete, required, wide }) => {
16333
+ const fieldId = `${uid}-${key2}`;
16334
+ const fieldError = addressErrors?.[key2];
16335
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: (0, import_utils26.cn)("space-y-1", wide && "sm:col-span-2"), children: [
16336
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { htmlFor: fieldId, className: "text-sm font-medium", children: t[key2] }),
16337
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16338
+ "input",
16339
+ {
16340
+ id: fieldId,
16341
+ type: "text",
16342
+ required,
16343
+ autoComplete,
16344
+ value: address[key2],
16345
+ onChange: (e) => onAddressChange({ ...address, [key2]: e.target.value }),
16346
+ "aria-invalid": fieldError ? true : void 0,
16347
+ "aria-describedby": fieldError ? `${fieldId}-error` : void 0,
16348
+ className: (0, import_utils26.cn)(
16349
+ INPUT_CLASS,
16350
+ fieldError ? "border-destructive" : "border-border focus:border-primary"
16351
+ )
16352
+ }
16353
+ ),
16354
+ fieldError ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { id: `${fieldId}-error`, className: "text-sm text-destructive", children: fieldError }) : null
16355
+ ] }, key2);
16356
+ }) })
16357
+ ] }) : null
16358
+ ]
16359
+ }
16360
+ );
16361
+ }
16362
+ function defaultCheckoutFulfillment(delivery) {
16363
+ if (!delivery) return null;
16364
+ if (delivery.methods.homeDelivery) return { type: "SHIPPING" };
16365
+ if (!delivery.methods.pickup) return null;
16366
+ const [only, ...rest] = delivery.pickupLocations;
16367
+ return only && rest.length === 0 ? { type: "PICKUP", pickupLocationId: only.id } : { type: "PICKUP" };
16368
+ }
16369
+ function quoteRequiresDelivery(quote) {
16370
+ return quote ? quote.lines.some((line) => line.isShippable) : true;
16371
+ }
16372
+ function toCheckoutFulfillmentFields(value, address, requiresDelivery = true) {
16373
+ if (!value || !requiresDelivery) return { fulfillment: { type: "SHIPPING" } };
16374
+ if (value.type === "PICKUP") {
16375
+ return { fulfillment: value.pickupLocationId ? { type: "PICKUP", pickupLocationId: value.pickupLocationId } : { type: "PICKUP" } };
16376
+ }
16377
+ const shippingAddress = {
16378
+ firstName: address.firstName.trim(),
16379
+ lastName: address.lastName.trim(),
16380
+ street: address.street.trim(),
16381
+ postalCode: address.postalCode.trim(),
16382
+ city: address.city.trim(),
16383
+ ...address.region.trim() ? { region: address.region.trim() } : {}
16384
+ };
16385
+ return { fulfillment: { type: "SHIPPING" }, shippingAddress };
16386
+ }
16387
+
16388
+ // src/components/checkout-quote-summary.tsx
16389
+ var import_utils27 = require("@reblu/site-ui/utils");
16390
+ var import_jsx_runtime31 = require("react/jsx-runtime");
16391
+ var DEFAULT_CHECKOUT_QUOTE_SUMMARY_LABELS = {
16392
+ subtotal: "Subtotal",
16393
+ discount: (codeOrLabel, isAutomatic) => isAutomatic ? codeOrLabel : `Descuento (${codeOrLabel})`,
16394
+ free: "Gratis",
16395
+ delivery: "Entrega",
16396
+ remainingForFree: (amount) => `Te faltan ${amount} para el env\xEDo gratis`,
16397
+ taxIncluded: (label) => `De los cuales ${label}`,
16398
+ total: "Total",
16399
+ taxesIncludedNote: "Impuestos incluidos",
16400
+ quantityTimesUnit: (quantity, unit) => `${quantity} \xD7 ${unit}`
16401
+ };
16402
+ function Row({
16403
+ name,
16404
+ value,
16405
+ className
16406
+ }) {
16407
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { "data-slot": "checkout-quote-row", className: (0, import_utils27.cn)("flex justify-between gap-4", className), children: [
16408
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dt", { children: name }),
16409
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dd", { className: "shrink-0 tabular-nums", children: value })
16410
+ ] });
16411
+ }
16412
+ function CheckoutQuoteSummary({
16413
+ quote,
16414
+ heading,
16415
+ headingLevel = 2,
16416
+ labels,
16417
+ currencyCode,
16418
+ locale,
16419
+ className
16420
+ }) {
16421
+ const t = { ...DEFAULT_CHECKOUT_QUOTE_SUMMARY_LABELS, ...labels };
16422
+ const price = (cents) => formatPrice(cents, currencyCode, locale);
16423
+ const { fulfillment, shipping, tax, discount } = quote;
16424
+ const Tag = `h${headingLevel}`;
16425
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("section", { "data-slot": "checkout-quote-summary", className: slotClassName("space-y-4", "", className), children: [
16426
+ heading ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Tag, { className: "text-lg font-semibold", children: heading }) : null,
16427
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "space-y-3 text-sm", children: quote.lines.map((line) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("li", { className: "flex justify-between gap-4", children: [
16428
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "min-w-0 space-y-0.5", children: [
16429
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "font-medium", children: line.name }),
16430
+ line.variantName ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-muted-foreground", children: line.variantName }) : null,
16431
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { className: "flex flex-wrap items-center gap-2 text-muted-foreground", children: [
16432
+ line.kindLabel ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { "data-slot": "checkout-quote-kind", className: "rounded-full border border-border px-2 py-0.5 text-xs font-medium text-foreground", children: line.kindLabel }) : null,
16433
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: t.quantityTimesUnit(line.quantity, price(line.unitPrice)) })
16434
+ ] })
16435
+ ] }),
16436
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "shrink-0 tabular-nums", children: price(line.total) })
16437
+ ] }, `${line.productId}-${line.variantId ?? ""}`)) }),
16438
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("dl", { className: "space-y-2 border-t border-border pt-3 text-sm", children: [
16439
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { name: t.subtotal, value: price(quote.subtotal) }),
16440
+ discount && discount.amount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
16441
+ Row,
16442
+ {
16443
+ className: "text-green-700 dark:text-green-400",
16444
+ name: t.discount(discount.isAutomatic ? discount.label ?? discount.code : discount.code, discount.isAutomatic),
16445
+ value: `\u2212${price(discount.amount)}`
16446
+ }
16447
+ ) : null,
16448
+ fulfillment.type ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
16449
+ Row,
16450
+ {
16451
+ name: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
16452
+ fulfillment.label ?? t.delivery,
16453
+ fulfillment.type === "PICKUP" && fulfillment.pickupLocation ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "block text-muted-foreground", children: fulfillment.pickupLocation.name }) : null
16454
+ ] }),
16455
+ value: fulfillment.type === "PICKUP" || shipping.isFree ? t.free : price(shipping.cost)
16456
+ }
16457
+ ) : null,
16458
+ tax.isLineVisible ? tax.breakdown.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
16459
+ Row,
16460
+ {
16461
+ className: tax.isIncluded ? "text-muted-foreground" : void 0,
16462
+ name: tax.isIncluded ? t.taxIncluded(entry.label) : entry.label,
16463
+ value: price(entry.amount)
16464
+ },
16465
+ entry.label
16466
+ )) : null,
16467
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { className: "border-t border-border pt-2 text-base font-bold", name: t.total, value: price(quote.total) })
16468
+ ] }),
16469
+ tax.isIncluded ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-sm text-muted-foreground", children: t.taxesIncludedNote }) : null,
16470
+ fulfillment.type === "SHIPPING" && !shipping.isFree && shipping.remainingForFree ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-sm text-muted-foreground", children: t.remainingForFree(price(shipping.remainingForFree)) }) : null,
16471
+ fulfillment.type && quote.deliveryEstimateText ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { "data-slot": "checkout-quote-estimate", className: "text-sm text-muted-foreground", children: quote.deliveryEstimateText }) : null,
16472
+ quote.discountError ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { role: "status", className: "text-sm text-destructive", children: quote.discountError.message }) : null,
16473
+ quote.blockingReason ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { role: "alert", className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: quote.blockingReason.message }) : null
16474
+ ] });
16475
+ }
16476
+
16477
+ // src/components/checkout-terms-acceptance.tsx
16478
+ var import_utils28 = require("@reblu/site-ui/utils");
16479
+ var import_jsx_runtime32 = require("react/jsx-runtime");
16480
+ function splitTermsLabel(label) {
16481
+ const at = label.indexOf("{terms}");
16482
+ return at === -1 ? [`${label} `, ""] : [label.slice(0, at), label.slice(at + "{terms}".length)];
16483
+ }
16484
+ function CheckoutTermsAcceptance({
16485
+ copy,
16486
+ termsHref,
16487
+ checked,
16488
+ onCheckedChange,
16489
+ error,
16490
+ newTabHint = "(se abre en una pesta\xF1a nueva)",
16491
+ id,
16492
+ className
16493
+ }) {
16494
+ if (!copy.termsVersion) return null;
16495
+ const boxId = id ?? "checkout-terms";
16496
+ const errorId = `${boxId}-error`;
16497
+ const [before, after] = splitTermsLabel(copy.termsCheckboxLabel).map(
16498
+ (part) => part.replaceAll("{tenant}", copy.tenantName)
16499
+ );
16500
+ const newTab = copy.isTermsLinkNewTab;
16501
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { "data-slot": "checkout-terms", className: (0, import_utils28.cn)("space-y-1", className), children: [
16502
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-start gap-3", children: [
16503
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16504
+ "input",
16505
+ {
16506
+ id: boxId,
16507
+ type: "checkbox",
16508
+ required: true,
16509
+ checked,
16510
+ onChange: (e) => onCheckedChange(e.target.checked),
16511
+ "aria-invalid": error ? true : void 0,
16512
+ "aria-describedby": error ? errorId : void 0,
16513
+ className: "mt-0.5 size-5 shrink-0 cursor-pointer accent-primary"
16514
+ }
16515
+ ),
16516
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { htmlFor: boxId, className: "text-sm leading-relaxed", children: [
16517
+ before,
16518
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
16519
+ "a",
16520
+ {
16521
+ href: copy.termsLinkUrl ?? termsHref,
16522
+ ...newTab ? { target: "_blank", rel: "noopener noreferrer" } : {},
16523
+ className: "font-medium underline underline-offset-2 hover:text-primary",
16524
+ children: [
16525
+ copy.termsLinkText,
16526
+ newTab ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
16527
+ " ",
16528
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "sr-only", children: newTabHint })
16529
+ ] }) : null
16530
+ ]
16531
+ }
16532
+ ),
16533
+ after
16534
+ ] })
16535
+ ] }),
16536
+ error ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { id: errorId, className: "pl-8 text-sm text-destructive", children: error }) : null
16537
+ ] });
16538
+ }
16539
+ function toCheckoutTermsFields(copy, accepted) {
16540
+ const version = copy?.termsVersion;
16541
+ return version ? { acceptsTerms: accepted, termsVersionId: version.id } : {};
16542
+ }
16543
+
16544
+ // src/components/checkout-pay-action.tsx
16545
+ var import_utils29 = require("@reblu/site-ui/utils");
16546
+ var import_jsx_runtime33 = require("react/jsx-runtime");
16547
+ function CheckoutPayAction({
16548
+ label,
16549
+ notice,
16550
+ submitting = false,
16551
+ submittingLabel = "Procesando\u2026",
16552
+ disabled = false,
16553
+ id = "checkout-pay",
16554
+ className,
16555
+ buttonClassName,
16556
+ noticeClassName
16557
+ }) {
16558
+ const noticeId = `${id}-notice`;
16559
+ const isDisabled = submitting || disabled;
16560
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { "data-slot": "checkout-pay-action", className: (0, import_utils29.cn)("space-y-3", className), children: [
16561
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
16562
+ "button",
16563
+ {
16564
+ type: "submit",
16565
+ disabled: isDisabled,
16566
+ "aria-busy": submitting || void 0,
16567
+ "aria-describedby": notice ? noticeId : void 0,
16568
+ className: buttonClassName ?? (0, import_utils29.cn)(
16569
+ "flex w-full items-center justify-center gap-2 rounded-xl px-4 py-3 text-base font-semibold transition-all",
16570
+ isDisabled ? "cursor-not-allowed bg-muted text-muted-foreground" : "cursor-pointer bg-primary text-primary-foreground hover:bg-primary/90"
16571
+ ),
16572
+ children: submitting ? submittingLabel : label
16573
+ }
16574
+ ),
16575
+ notice ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { id: noticeId, "data-slot": "checkout-pay-notice", className: noticeClassName ?? "text-sm text-muted-foreground", children: notice }) : null
16576
+ ] });
16577
+ }
16578
+
16579
+ // src/components/contact-interest-field.tsx
16580
+ var import_utils30 = require("@reblu/site-ui/utils");
16581
+ var import_jsx_runtime34 = require("react/jsx-runtime");
16181
16582
  function ContactInterestField({
16182
16583
  interest,
16183
16584
  value,
@@ -16194,18 +16595,18 @@ function ContactInterestField({
16194
16595
  else next2.delete(option2);
16195
16596
  onChange(interest.options.filter((candidate) => next2.has(candidate)));
16196
16597
  };
16197
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("fieldset", { "data-slot": "contact-interest", className: (0, import_utils26.cn)("space-y-2", className), children: [
16198
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("legend", { className: "text-sm font-medium", children: interest.label }),
16199
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex flex-col gap-2", children: interest.options.map((option2, index) => {
16598
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("fieldset", { "data-slot": "contact-interest", className: (0, import_utils30.cn)("space-y-2", className), children: [
16599
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("legend", { className: "text-sm font-medium", children: interest.label }),
16600
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex flex-col gap-2", children: interest.options.map((option2, index) => {
16200
16601
  const id = `${idPrefix}-${index}`;
16201
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
16602
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
16202
16603
  "label",
16203
16604
  {
16204
16605
  htmlFor: id,
16205
16606
  "data-slot": "contact-interest-option",
16206
16607
  className: "flex items-center gap-2 text-sm",
16207
16608
  children: [
16208
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16609
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
16209
16610
  "input",
16210
16611
  {
16211
16612
  id,
@@ -16234,13 +16635,19 @@ var import_site_contracts = require("@reblu/site-contracts");
16234
16635
  CartAdjustmentsNotice,
16235
16636
  CartLineList,
16236
16637
  CartSummary,
16638
+ CheckoutDeliveryChoice,
16237
16639
  CheckoutForm,
16238
16640
  CheckoutLoginPrompt,
16641
+ CheckoutPayAction,
16642
+ CheckoutQuoteSummary,
16643
+ CheckoutTermsAcceptance,
16239
16644
  ContactInterestField,
16240
16645
  CourseCatalogFilters,
16241
16646
  CourseDescription,
16242
16647
  CoursePurchaseTerms,
16243
16648
  DATA_REQUEST_TYPES,
16649
+ DEFAULT_CHECKOUT_DELIVERY_CHOICE_LABELS,
16650
+ DEFAULT_CHECKOUT_QUOTE_SUMMARY_LABELS,
16244
16651
  DEFAULT_COURSE_CATALOG_FILTERS_LABELS,
16245
16652
  DEFAULT_COURSE_PRICE_BANDS,
16246
16653
  DEFAULT_COURSE_PURCHASE_TERMS_LABELS,
@@ -16252,6 +16659,7 @@ var import_site_contracts = require("@reblu/site-contracts");
16252
16659
  DEFAULT_TRUST_BADGE_HEADINGS,
16253
16660
  DEFAULT_TRUST_BADGE_TYPE_ORDER,
16254
16661
  DEFAULT_TRUST_ICONS,
16662
+ EMPTY_CHECKOUT_ADDRESS,
16255
16663
  EMPTY_FULL_INVOICE_VALUE,
16256
16664
  FaqAccordion,
16257
16665
  FullInvoiceFields,
@@ -16275,17 +16683,21 @@ var import_site_contracts = require("@reblu/site-contracts");
16275
16683
  buildFaqPageJsonLd,
16276
16684
  buildShareUrls,
16277
16685
  collectFaqItems,
16686
+ defaultCheckoutFulfillment,
16278
16687
  formatPrice,
16279
16688
  getShopErrorMessage,
16280
16689
  isAllowedYouTubeHost,
16281
16690
  isOverSimplifiedInvoiceCap,
16282
16691
  markdownToPlainText,
16283
16692
  markdownToSafeHtml,
16693
+ quoteRequiresDelivery,
16284
16694
  readingTime,
16285
16695
  sanitizeHtml,
16286
16696
  shopIssuesInvoices,
16287
16697
  shouldRenderShopFilters,
16288
- toCheckoutInvoiceFields
16698
+ toCheckoutFulfillmentFields,
16699
+ toCheckoutInvoiceFields,
16700
+ toCheckoutTermsFields
16289
16701
  });
16290
16702
  /*! Bundled license information:
16291
16703