@sezzle/sezzle-react-widget 3.1.7 → 3.2.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
@@ -402,6 +402,19 @@ function getCurrency(priceString) {
402
402
  return currencyMatch ? currencyMatch[0] : defaultCurrency;
403
403
  }
404
404
 
405
+ /**
406
+ * Renders a numeric value with the decimal separator appropriate for the
407
+ * language: a period for English, a comma for French/Spanish. Only the decimal
408
+ * separator is swapped; no grouping is applied.
409
+ * @param value - number or numeric string (e.g. an APR like 9.99)
410
+ * @param lang - Language code (en, fr, es)
411
+ * @return string
412
+ */
413
+ function formatNumberForLocale(value, lang) {
414
+ var str = String(value);
415
+ return lang === 'fr' || lang === 'es' ? str.replace('.', ',') : str;
416
+ }
417
+
405
418
  /**
406
419
  * Returns the translation object for the specified language
407
420
  * @param currentLang - Language code (en, fr, es)
@@ -416,6 +429,218 @@ function getTranslations(currentLang) {
416
429
  return translationsMap[currentLang];
417
430
  }
418
431
 
432
+ function _toConsumableArray$1(r) { return _arrayWithoutHoles$1(r) || _iterableToArray$1(r) || _unsupportedIterableToArray$1(r) || _nonIterableSpread$1(); }
433
+ function _nonIterableSpread$1() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
434
+ function _iterableToArray$1(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
435
+ function _arrayWithoutHoles$1(r) { if (Array.isArray(r)) return _arrayLikeToArray$1(r); }
436
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$1(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
437
+ function _unsupportedIterableToArray$1(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$1(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$1(r, a) : void 0; } }
438
+ function _arrayLikeToArray$1(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
439
+ function ownKeys$4(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
440
+ function _objectSpread$4(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$4(Object(t), !0).forEach(function (r) { _defineProperty$4(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$4(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
441
+ function _defineProperty$4(e, r, t) { return (r = _toPropertyKey$4(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
442
+ function _toPropertyKey$4(t) { var i = _toPrimitive$4(t, "string"); return "symbol" == _typeof$4(i) ? i : i + ""; }
443
+ function _toPrimitive$4(t, r) { if ("object" != _typeof$4(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof$4(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
444
+ function _typeof$4(o) { "@babel/helpers - typeof"; return _typeof$4 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof$4(o); }
445
+ // Long-term (LT) product configuration.
446
+ //
447
+ // The widget supports long-term payment options whose defaults differ by
448
+ // lending partner. To make per-partner rollouts easy, each partner's complete
449
+ // set of LT defaults is bundled under a neutral alias ("a", "b", ...). The
450
+ // alias is deliberately non-branded so the lending partner is never exposed to
451
+ // merchants. An account manager guides the merchant on which alias to use based
452
+ // on their enrollment, so the merchant no longer has to set every LT field by
453
+ // hand. "a" is the default fallback preset.
454
+ //
455
+ // Every LT option follows a consistent contract: 0 (or unset) means "not set."
456
+ // To disable LT entirely, omit both `minPriceLT` and `LTgroup`.
457
+ //
458
+ // Units note: unlike the backend LT API (which uses cents), every LT value in
459
+ // this widget is expressed in whole currency units (dollars), matching the rest
460
+ // of this project's config — minPriceLT, maxPriceLT, and the termsToShow
461
+ // thresholds are all dollar amounts.
462
+
463
+ var DEFAULT_LT_GROUP = 'a';
464
+
465
+ // Recursively freeze an object and all nested objects/arrays. The presets below
466
+ // are shared, long-lived references that resolve* helpers hand out directly
467
+ // (e.g. resolveTermsToShow returns the preset's termsToShow, including its term
468
+ // arrays, by reference). Freezing makes any accidental downstream mutation
469
+ // (e.g. config.termsToShow.default.push(12)) throw instead of silently
470
+ // corrupting the preset for the lifetime of the page.
471
+ function deepFreeze(obj) {
472
+ for (var _i = 0, _Object$values = Object.values(obj); _i < _Object$values.length; _i++) {
473
+ var value = _Object$values[_i];
474
+ if (value && _typeof$4(value) === 'object' && !Object.isFrozen(value)) {
475
+ deepFreeze(value);
476
+ }
477
+ }
478
+ return Object.freeze(obj);
479
+ }
480
+
481
+ // Per-partner presets. Each preset is a COMPLETE set of LT defaults:
482
+ // minPriceLT – lowest price (inclusive) eligible for LT
483
+ // maxPriceLT – highest price (inclusive) eligible for LT
484
+ // minAPR – lowest APR offered; lower bound of the disclaimer APR range
485
+ // medianAPR – representative APR; drives per-card monthly payment + per-card APR display
486
+ // maxAPR – highest APR offered; upper bound of the disclaimer APR range
487
+ // termsToShow – price-threshold → term-length map (see termsToShow shape below)
488
+ //
489
+ // termsToShow shape: keys are price thresholds in dollars, values are arrays of
490
+ // term lengths in months. The `default` key handles prices below all
491
+ // thresholds. A price selects the array for the highest threshold it strictly
492
+ // exceeds, mirroring the previously hardcoded tiers.
493
+ var LT_GROUPS = deepFreeze({
494
+ // "a" is seeded from this project's prior production values
495
+ // (APR range 9.99–34.99, median 21.99, maxPriceLT 15000, and the original
496
+ // hardcoded term tiers).
497
+ a: {
498
+ minPriceLT: 150,
499
+ maxPriceLT: 15000,
500
+ minAPR: 9.99,
501
+ medianAPR: 21.99,
502
+ maxAPR: 34.99,
503
+ termsToShow: {
504
+ "default": [3, 6, 9],
505
+ 300: [6, 9, 12],
506
+ 500: [12, 18, 24],
507
+ 1000: [24, 36, 48]
508
+ }
509
+ },
510
+ b: {
511
+ minPriceLT: 400,
512
+ maxPriceLT: 8000,
513
+ minAPR: 24.99,
514
+ medianAPR: 29.99,
515
+ maxAPR: 35.99,
516
+ termsToShow: {
517
+ "default": [3, 6, 9],
518
+ 600: [6, 9, 12],
519
+ 800: [9, 12, 24],
520
+ 1000: [12, 24, 36]
521
+ }
522
+ }
523
+ });
524
+
525
+ // Resolve an LTgroup alias to its canonical (lowercased) preset key, or null
526
+ // when no alias is given. An unrecognized (non-empty) alias warns (listing the
527
+ // accepted values) and resolves to null so callers fall back to the default.
528
+ function normalizeGroup(alias) {
529
+ if (alias === undefined || alias === null || alias === '') return null;
530
+ var key = String(alias).toLowerCase();
531
+ if (LT_GROUPS[key]) return key;
532
+ console.warn("[Sezzle] Unknown LTgroup \"".concat(alias, "\". Accepted values: ").concat(Object.keys(LT_GROUPS).map(function (k) {
533
+ return "\"".concat(k, "\"");
534
+ }).join(', '), ". Falling back to \"").concat(DEFAULT_LT_GROUP, "\"."));
535
+ return null;
536
+ }
537
+
538
+ // True when `value` is a well-formed termsToShow map: an object whose values are
539
+ // non-empty arrays of positive numbers (months).
540
+ function isValidTermsToShow(value) {
541
+ if (!value || _typeof$4(value) !== 'object' || Array.isArray(value)) return false;
542
+ var entries = Object.values(value);
543
+ if (entries.length === 0) return false;
544
+ return entries.every(function (arr) {
545
+ return Array.isArray(arr) && arr.length > 0 && arr.every(function (n) {
546
+ return Number.isFinite(n) && n > 0;
547
+ });
548
+ });
549
+ }
550
+
551
+ // Resolve a merchant-supplied termsToShow against the group preset. Malformed
552
+ // input warns (with the expected shape) and falls back to the preset. A valid
553
+ // map missing the `default` key warns and borrows the preset's default so
554
+ // below-threshold lookups never fall through.
555
+ function resolveTermsToShow(provided, presetTerms) {
556
+ if (provided === undefined || provided === null) return presetTerms;
557
+ if (!isValidTermsToShow(provided)) {
558
+ console.warn('[Sezzle] Malformed termsToShow. Expected an object mapping price ' + 'thresholds (numbers, in dollars) to arrays of term lengths in months, ' + 'plus a "default" key for prices below all thresholds, e.g. ' + '{ default: [3, 6, 9], 500: [12, 18, 24] }. Falling back to the ' + 'LTgroup preset.');
559
+ return presetTerms;
560
+ }
561
+ if (!Array.isArray(provided["default"])) {
562
+ console.warn('[Sezzle] termsToShow is missing a "default" key for prices below all ' + "thresholds. Using the LTgroup preset's default.");
563
+ return _objectSpread$4(_objectSpread$4({}, provided), {}, {
564
+ "default": presetTerms["default"]
565
+ });
566
+ }
567
+ return provided;
568
+ }
569
+
570
+ // Pick an explicit prop when it is "set" (> 0), otherwise the preset value.
571
+ // A value of 0 is never a valid LT setting, so it is treated as "not set."
572
+ function pickPrice(value, fallback) {
573
+ return Number(value) > 0 ? Number(value) : fallback;
574
+ }
575
+
576
+ // Resolve the effective LT config from widget props.
577
+ //
578
+ // Every LT value defaults to a group preset, falling back to group "a" even
579
+ // when LT is off, so maxPriceLT / the APRs / termsToShow are never 0 or null
580
+ // downstream. `minPriceLT` is the sole exception: it is the render trigger
581
+ // (the widget shows LT only when minPriceLT > 0), so it stays 0 when LT is
582
+ // disabled — i.e. when neither LTgroup nor minPriceLT is provided.
583
+ function resolveLTConfig() {
584
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
585
+ var explicitGroup = normalizeGroup(props.LTgroup);
586
+ // Backcompat: pre-LTgroup configs enabled LT via minPriceLT alone. When that's
587
+ // set without an explicit LTgroup, auto-resolve to the default preset so the
588
+ // remaining LT defaults come from the original group "a".
589
+ var minPriceLTSet = Number(props.minPriceLT) > 0;
590
+ var group = explicitGroup || (minPriceLTSet ? DEFAULT_LT_GROUP : null);
591
+ var groupDefaults = LT_GROUPS[group] || LT_GROUPS[DEFAULT_LT_GROUP];
592
+ return {
593
+ minPriceLT: pickPrice(props.minPriceLT, group ? groupDefaults.minPriceLT : 0),
594
+ maxPriceLT: pickPrice(props.maxPriceLT, groupDefaults.maxPriceLT),
595
+ minAPR: pickPrice(props.minAPR, groupDefaults.minAPR),
596
+ medianAPR: pickPrice(props.medianAPR, groupDefaults.medianAPR),
597
+ maxAPR: pickPrice(props.maxAPR, groupDefaults.maxAPR),
598
+ termsToShow: resolveTermsToShow(props.termsToShow, groupDefaults.termsToShow)
599
+ };
600
+ }
601
+
602
+ // Select the term-length array for a price from a termsToShow map. Returns the
603
+ // array for the highest dollar threshold the price strictly exceeds, falling
604
+ // back to the `default` key. Returns undefined only when the map is missing /
605
+ // has no usable default — callers guard against that.
606
+ function selectTermsToShow(price, termsConfig) {
607
+ if (!termsConfig || _typeof$4(termsConfig) !== 'object') return undefined;
608
+ var thresholds = Object.keys(termsConfig).filter(function (k) {
609
+ return k !== 'default';
610
+ }).map(Number).filter(Number.isFinite).sort(function (a, b) {
611
+ return a - b;
612
+ });
613
+ var selected = termsConfig["default"];
614
+ var _iterator = _createForOfIteratorHelper(thresholds),
615
+ _step;
616
+ try {
617
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
618
+ var threshold = _step.value;
619
+ if (price > threshold) selected = termsConfig[threshold];
620
+ }
621
+ } catch (err) {
622
+ _iterator.e(err);
623
+ } finally {
624
+ _iterator.f();
625
+ }
626
+ return selected;
627
+ }
628
+
629
+ // Min and max term-month across the whole termsToShow map (the union of every
630
+ // term array, including `default`). Used for the disclaimer's term-length
631
+ // bounds. Returns null when no usable terms exist.
632
+ function termMonthBounds(termsConfig) {
633
+ if (!termsConfig || _typeof$4(termsConfig) !== 'object') return null;
634
+ var months = Object.values(termsConfig).filter(Array.isArray).flat().filter(function (n) {
635
+ return Number.isFinite(n);
636
+ });
637
+ if (months.length === 0) return null;
638
+ return {
639
+ min: Math.min.apply(Math, _toConsumableArray$1(months)),
640
+ max: Math.max.apply(Math, _toConsumableArray$1(months))
641
+ };
642
+ }
643
+
419
644
  var PI5_MIN_PRICE = 50;
420
645
  function isProductEligibleLT(priceText, minPriceLT, maxPriceLT) {
421
646
  if (!minPriceLT) return false;
@@ -439,18 +664,6 @@ function isInputAmountValid(priceText, minPrice, maxPrice, minPriceLT, maxPriceL
439
664
  var upper = minPriceLT > 0 ? Math.max(maxPrice, maxPriceLT || 0) : maxPrice;
440
665
  return price >= minPrice && price <= upper;
441
666
  }
442
- function termsToShow(price) {
443
- switch (true) {
444
- case price > 1000:
445
- return [24, 36, 48];
446
- case price > 500:
447
- return [12, 18, 24];
448
- case price > 300:
449
- return [6, 9, 12];
450
- default:
451
- return [3, 6, 9];
452
- }
453
- }
454
667
  function addDelimiters(priceString) {
455
668
  var parsedPrice = Number(priceString).toFixed(2);
456
669
  if (parsedPrice.length > 6) {
@@ -470,12 +683,24 @@ function calculateMonthlyWithInterest(priceText, term, APR) {
470
683
  return price / term;
471
684
  }
472
685
  }
473
- function getFormattedPrice(price, numberOfPayments, minPriceLT, maxPriceLT, bestAPR) {
686
+ function getFormattedPrice(price, numberOfPayments, minPriceLT, maxPriceLT, medianAPR, termsConfig) {
474
687
  var priceString = parsePriceString(price);
475
688
  var priceReplacer = parsePrice(price);
476
689
  var formatter = price.replace(priceString, '{price}');
477
- var terms = termsToShow(priceReplacer);
478
- var sezzleInstallmentPrice = isProductEligibleLT(priceString, minPriceLT, maxPriceLT) ? calculateMonthlyWithInterest(priceString, terms[terms.length - 1], bestAPR) : priceReplacer / numberOfPayments;
690
+ var sezzleInstallmentPrice;
691
+ if (isProductEligibleLT(priceString, minPriceLT, maxPriceLT)) {
692
+ var terms = selectTermsToShow(priceReplacer, termsConfig);
693
+ // Defensive guard: when LT-eligible but no terms match (e.g. a malformed
694
+ // termsToShow that slipped past validation), fall back to the bi-weekly
695
+ // installment price rather than producing NaN.
696
+ if (Array.isArray(terms) && terms.length > 0) {
697
+ sezzleInstallmentPrice = calculateMonthlyWithInterest(priceString, terms[terms.length - 1], medianAPR);
698
+ } else {
699
+ sezzleInstallmentPrice = priceReplacer / numberOfPayments;
700
+ }
701
+ } else {
702
+ sezzleInstallmentPrice = priceReplacer / numberOfPayments;
703
+ }
479
704
  var sezzleInstallmentFormattedPrice = formatter.replace('{price}', sezzleInstallmentPrice.toFixed(2));
480
705
  return sezzleInstallmentFormattedPrice;
481
706
  }
@@ -521,10 +746,6 @@ var CAROUSEL_MAX_TAB = 3;
521
746
  var INPUT_DEBOUNCE_DELAY_MS = 150;
522
747
  var CURRENCY_REGEX_GLOBAL = /[$€£₤₹]/g;
523
748
  var SANITIZE_REGEX = /[^0-9,.$€£₤₹]/g;
524
- var LT_APR_MIN = 9.99;
525
- var LT_APR_MAX = 34.99;
526
- var LT_TERM_MIN = 3;
527
- var LT_TERM_MAX = 48;
528
749
  function computeEligibility(priceString, opts) {
529
750
  return {
530
751
  pi4: isProductEligiblePI4(priceString, opts.minPrice, opts.maxPrice),
@@ -535,10 +756,13 @@ function computeEligibility(priceString, opts) {
535
756
  function formatLTAmount(currency, value) {
536
757
  return currency + addDelimiters(value);
537
758
  }
538
- function generateBiweeklyCard(numberOfPayments, currency, priceString, minPriceLT, maxPriceLT, bestAPR, translations) {
759
+ function generateBiweeklyCard(numberOfPayments, currency, priceString, translations) {
539
760
  var classModifier = numberOfPayments === 4 ? 'fourth' : 'fifth';
540
761
  var dashWidth = numberOfPayments === 4 ? 30 : 22;
541
- var installmentPrice = getFormattedPrice(currency + priceString, numberOfPayments, minPriceLT, maxPriceLT, bestAPR);
762
+ // Biweekly cards always show the bi-weekly installment (price / numberOfPayments),
763
+ // never the long-term monthly amount. Passing minPriceLT/maxPriceLT = 0 forces
764
+ // getFormattedPrice down the non-LT branch even for LT-eligible prices.
765
+ var installmentPrice = getFormattedPrice(currency + priceString, numberOfPayments, 0, 0, 0, null);
542
766
  var pillLabel = numberOfPayments === 5 ? "".concat(translations.MultiPlanpayIn, " 5 <sup>TM</sup>") : "".concat(translations.MultiPlanpayIn, " ").concat(numberOfPayments);
543
767
  var installments = [];
544
768
  for (var i = 0; i < numberOfPayments; i++) {
@@ -550,30 +774,31 @@ function generateBiweeklyCard(numberOfPayments, currency, priceString, minPriceL
550
774
  }
551
775
  return "\n <div class='payment-card ".concat(numberOfPayments, "-pay-installment-card'>\n <div class='plan-summary'>\n <div class='purple'>\n <div class='left'>\n <span class='price ").concat(numberOfPayments, "-pay-installment'>").concat(installmentPrice, "</span>\n <span class='due'>").concat(translations.today, "</span>\n </div>\n <div class='right'>\n <span class='pill'>").concat(pillLabel, "</span>\n </div>\n </div>\n <div class='grey'>\n <span class=\"").concat(numberOfPayments, "-pay-installment\">").concat(installmentPrice, "</span> ").concat(translations.MultiPlanevery2Weeks, "\n </div>\n </div>\n <div class='payment-breakdown'>\n ").concat(installments.join(''), "\n </div>\n </div>\n ");
552
776
  }
553
- function generateMonthlyCard(months, currency, priceString, bestAPR, translations) {
554
- var monthly = calculateMonthlyWithInterest(priceString, months, bestAPR);
777
+ function generateMonthlyCard(months, currency, priceString, medianAPR, translations, lang) {
778
+ var monthly = calculateMonthlyWithInterest(priceString, months, medianAPR);
555
779
  var total = monthly * months;
556
780
  var interest = total - Number(priceString);
557
- return "\n <div class='payment-card monthly-installment-card' data-months='".concat(months, "'>\n <div class='plan-summary'>\n <div class='purple'>\n <div class='left'>\n <span class='price monthly-amount' data-months='").concat(months, "'>").concat(formatLTAmount(currency, monthly), "</span>\n <span class='due' aria-label='").concat(translations.LTperMonth, "'>\n <span aria-hidden='true'>").concat(translations.LTmonthlyAmount, "</span>\n </span>\n </div>\n <div class='right'>\n <span class='pill'>").concat(months, " ").concat(translations.LTtermLength, "</span>\n </div>\n </div>\n </div>\n <div class='plan-details monthly-plan-details'>\n <div class='monthly-detail-row' aria-label='").concat(translations.LTreadApr, " ").concat(bestAPR, " ").concat(translations.LTpercent, "'>\n <span class='detail-label' aria-hidden='true'>").concat(translations.LTsampleApr, "</span>\n <span class='detail-value monthly-apr' aria-hidden='true'>").concat(bestAPR, "%</span>\n </div>\n <div class='monthly-detail-row'>\n <span class='detail-label'>").concat(translations.LTinterest, "</span>\n <span class='detail-value monthly-interest' data-months='").concat(months, "'>").concat(formatLTAmount(currency, interest), "</span>\n </div>\n <div class='monthly-detail-row'>\n <span class='detail-label'>").concat(translations.LTadjustedTotal, "</span>\n <span class='detail-value monthly-total' data-months='").concat(months, "'>").concat(formatLTAmount(currency, total), "</span>\n </div>\n </div>\n </div>\n ");
781
+ var aprDisplay = formatNumberForLocale(medianAPR, lang);
782
+ return "\n <div class='payment-card monthly-installment-card' data-months='".concat(months, "'>\n <div class='plan-summary'>\n <div class='purple'>\n <div class='left'>\n <span class='price monthly-amount' data-months='").concat(months, "'>").concat(formatLTAmount(currency, monthly), "</span>\n <span class='due' aria-label='").concat(translations.LTperMonth, "'>\n <span aria-hidden='true'>").concat(translations.LTmonthlyAmount, "</span>\n </span>\n </div>\n <div class='right'>\n <span class='pill'>").concat(months, " ").concat(translations.LTtermLength, "</span>\n </div>\n </div>\n </div>\n <div class='plan-details monthly-plan-details'>\n <div class='monthly-detail-row' aria-label='").concat(translations.LTreadApr, " ").concat(aprDisplay, " ").concat(translations.LTpercent, "'>\n <span class='detail-label' aria-hidden='true'>").concat(translations.LTsampleApr, "</span>\n <span class='detail-value monthly-apr' aria-hidden='true'>").concat(aprDisplay, "%</span>\n </div>\n <div class='monthly-detail-row'>\n <span class='detail-label'>").concat(translations.LTinterest, "</span>\n <span class='detail-value monthly-interest' data-months='").concat(months, "'>").concat(formatLTAmount(currency, interest), "</span>\n </div>\n <div class='monthly-detail-row'>\n <span class='detail-label'>").concat(translations.LTadjustedTotal, "</span>\n <span class='detail-value monthly-total' data-months='").concat(months, "'>").concat(formatLTAmount(currency, total), "</span>\n </div>\n </div>\n </div>\n ");
558
783
  }
559
784
  function featureCheckSvg() {
560
785
  return "<svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6.66667 0C2.98667 0 0 2.98667 0 6.66667C0 10.3467 2.98667 13.3333 6.66667 13.3333C10.3467 13.3333 13.3333 10.3467 13.3333 6.66667C13.3333 2.98667 10.3467 0 6.66667 0ZM6.66667 12C3.72667 12 1.33333 9.60667 1.33333 6.66667C1.33333 3.72667 3.72667 1.33333 6.66667 1.33333C9.60667 1.33333 12 3.72667 12 6.66667C12 9.60667 9.60667 12 6.66667 12ZM9.25333 4.19333L5.33333 8.11333L4.08 6.86C3.82 6.6 3.4 6.6 3.14 6.86C2.88 7.12 2.88 7.54 3.14 7.8L4.86667 9.52667C5.12667 9.78667 5.54667 9.78667 5.80667 9.52667L10.2 5.13333C10.46 4.87333 10.46 4.45333 10.2 4.19333C9.94 3.93333 9.51333 3.93333 9.25333 4.19333Z\" fill=\"#8333D4\"/>\n </svg>";
561
786
  }
562
787
  function generateBiweeklyInner(eligibility, currency, priceString, opts, translations) {
563
788
  if (!eligibility.pi4) return '';
564
- return "\n ".concat(generateBiweeklyCard(4, currency, priceString, opts.minPriceLT, opts.maxPriceLT, opts.bestAPR, translations), "\n ").concat(eligibility.pi5 ? generateBiweeklyCard(5, currency, priceString, opts.minPriceLT, opts.maxPriceLT, opts.bestAPR, translations) : '', "\n ");
789
+ return "\n ".concat(generateBiweeklyCard(4, currency, priceString, translations), "\n ").concat(eligibility.pi5 ? generateBiweeklyCard(5, currency, priceString, translations) : '', "\n ");
565
790
  }
566
- function generateMonthlyInner(eligibility, currency, priceString, opts, translations) {
791
+ function generateMonthlyInner(eligibility, currency, priceString, opts, translations, lang) {
567
792
  if (!eligibility.lt) return '';
568
- var terms = termsToShow(parsePrice(priceString));
793
+ var terms = selectTermsToShow(parsePrice(priceString), opts.termsToShow) || [];
569
794
  var cards = terms.map(function (months) {
570
- return generateMonthlyCard(months, currency, priceString, opts.bestAPR, translations);
795
+ return generateMonthlyCard(months, currency, priceString, opts.medianAPR, translations, lang);
571
796
  }).join('');
572
797
  var seeDetails = translations.LTseeDetails;
573
798
  var hideDetails = translations.LThideDetails;
574
799
  return "\n ".concat(cards, "\n <div class=\"features-accordion\">\n <div class=\"accordion-title-bar\">\n <span class=\"accordion-title\" aria-hidden='true'>").concat(seeDetails, "</span>\n <button class=\"accordion-icon accordion-toggle\" aria-expanded=\"false\" aria-controls=\"features-drawer\" aria-label='").concat(seeDetails, "' data-label-expand='").concat(seeDetails, "' data-label-collapse='").concat(hideDetails, "'>\n <svg class=\"accordion-icon-expand\" width=\"12\" height=\"7\" viewBox=\"0 0 12 7\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9.4625 0.2925L5.5825 4.1725L1.7025 0.2925C1.3125 -0.0975 0.6825 -0.0975 0.2925 0.2925C-0.0975 0.6825 -0.0975 1.3125 0.2925 1.7025L4.8825 6.2925C5.2725 6.6825 5.9025 6.6825 6.2925 6.2925L10.8825 1.7025C11.2725 1.3125 11.2725 0.6825 10.8825 0.2925C10.4925 -0.0875 9.8525 -0.0975 9.4625 0.2925Z\" fill=\"#8333D4\"/>\n </svg>\n <svg class=\"accordion-icon-collapse\" style=\"display:none\" width=\"12\" height=\"7\" viewBox=\"0 0 12 7\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.8825 0.2925L0.2925 4.8825C-0.0975 5.2725 -0.0975 5.9025 0.2925 6.2925C0.6825 6.6825 1.3125 6.6825 1.7025 6.2925L5.5925 2.4125L9.4725 6.2925C9.8625 6.6825 10.4925 6.6825 10.8825 6.2925C11.2725 5.9025 11.2725 5.2725 10.8825 4.8825L6.2925 0.2925C5.9125 -0.0975 5.2725 -0.0975 4.8825 0.2925Z\" fill=\"#8333D4\"/>\n </svg>\n </button>\n </div>\n <div id=\"features-drawer\" class=\"features-drawer\" style=\"display: none;\">\n <div class=\"single-feature\"><div>").concat(featureCheckSvg(), "</div><span>").concat(translations.LTsingleFeatureAffordable, "</span></div>\n <div class=\"single-feature\"><div>").concat(featureCheckSvg(), "</div><span>").concat(translations.LTsingleFeaturePrequalify, "</span></div>\n <div class=\"single-feature\"><div>").concat(featureCheckSvg(), "</div><span>").concat(translations.LTsingleFeatureTrusted, "</span></div>\n </div>\n </div>\n ");
575
800
  }
576
- function generateTermsInner(eligibility, translations) {
801
+ function generateTermsInner(eligibility, translations, opts, lang) {
577
802
  var webBank = '';
578
803
  if (eligibility.pi4) {
579
804
  var productTerms = eligibility.pi5 ? translations.webBankTermsPI5 : translations.webBankTermsPI4;
@@ -581,7 +806,14 @@ function generateTermsInner(eligibility, translations) {
581
806
  }
582
807
  var ltTerms = '';
583
808
  if (eligibility.lt) {
584
- var ltTerms3 = (translations.LTterms3 || '* Subject to credit approval by a third party lender.').replace('{minAPR}', LT_APR_MIN).replace('{maxAPR}', LT_APR_MAX).replace('{minTermMonths}', LT_TERM_MIN).replace('{maxTermMonths}', LT_TERM_MAX);
809
+ // APR range comes from the resolved LT config; term-month bounds derive from
810
+ // the union of every termsToShow array. APR values render with the
811
+ // locale-appropriate decimal separator.
812
+ var bounds = termMonthBounds(opts.termsToShow) || {
813
+ min: '',
814
+ max: ''
815
+ };
816
+ var ltTerms3 = (translations.LTterms3 || '* Subject to credit approval by a third party lender.').replace('{minAPR}', formatNumberForLocale(opts.minAPR, lang)).replace('{maxAPR}', formatNumberForLocale(opts.maxAPR, lang)).replace('{minTermMonths}', bounds.min).replace('{maxTermMonths}', bounds.max);
585
817
  ltTerms = "<p class=\"terms lt-terms\">".concat(ltTerms3, "</p>");
586
818
  }
587
819
  return "\n <p class=\"terms\"><span>".concat(translations.terms1, "</span><br /><span>").concat(translations.termsHiw, "</span></p>\n <p class=\"terms\">").concat(translations.terms2, "</p>\n ").concat(webBank, "\n ").concat(ltTerms, "\n ");
@@ -695,7 +927,7 @@ function attachFeaturesAccordion(modalNode) {
695
927
  }
696
928
 
697
929
  // Swap in re-rendered HTML for the sections that depend on the input amount.
698
- function renderDynamicSections(modalNode, currency, priceString, opts, translations) {
930
+ function renderDynamicSections(modalNode, currency, priceString, opts, translations, lang) {
699
931
  var eligibility = computeEligibility(priceString, opts);
700
932
  var container = modalNode.querySelector('#sezzle-modal-container');
701
933
  if (container) container.classList.toggle('pi4-only', !eligibility.pi5);
@@ -706,12 +938,12 @@ function renderDynamicSections(modalNode, currency, priceString, opts, translati
706
938
  }
707
939
  var monthly = modalNode.querySelector('.payment-cards-monthly');
708
940
  if (monthly) {
709
- monthly.innerHTML = generateMonthlyInner(eligibility, currency, priceString, opts, translations);
941
+ monthly.innerHTML = generateMonthlyInner(eligibility, currency, priceString, opts, translations, lang);
710
942
  monthly.style.display = eligibility.lt ? '' : 'none';
711
943
  if (eligibility.lt) attachFeaturesAccordion(modalNode);
712
944
  }
713
945
  var terms = modalNode.querySelector('.terms-container');
714
- if (terms) terms.innerHTML = generateTermsInner(eligibility, translations);
946
+ if (terms) terms.innerHTML = generateTermsInner(eligibility, translations, opts, lang);
715
947
  }
716
948
  function handleMultiPlanInput(modalNode, opts, initialCurrency) {
717
949
  var input = modalNode.querySelector('.input-amount');
@@ -719,7 +951,8 @@ function handleMultiPlanInput(modalNode, opts, initialCurrency) {
719
951
  if (!input || input.dataset.listenersAdded === 'true') return;
720
952
  var currency = initialCurrency;
721
953
  var debounceTimer = null;
722
- var translations = getTranslations(getLanguage());
954
+ var lang = getLanguage();
955
+ var translations = getTranslations(lang);
723
956
  input.addEventListener('click', function (e) {
724
957
  return e.stopPropagation();
725
958
  });
@@ -741,7 +974,7 @@ function handleMultiPlanInput(modalNode, opts, initialCurrency) {
741
974
  }
742
975
  input.classList.remove('input-error');
743
976
  if (container) container.classList.remove('input-error');
744
- renderDynamicSections(modalNode, currency, priceString, opts, translations);
977
+ renderDynamicSections(modalNode, currency, priceString, opts, translations, lang);
745
978
  }, INPUT_DEBOUNCE_DELAY_MS);
746
979
  });
747
980
  input.dataset.listenersAdded = 'true';
@@ -753,7 +986,8 @@ function handleMultiPlanInput(modalNode, opts, initialCurrency) {
753
986
  // minPrice=0 relaxation as the initial render so PI4 is always visible on open.
754
987
  function resetMultiPlanModal(modalNode, rawPrice, opts) {
755
988
  if (!modalNode) return;
756
- var translations = getTranslations(getLanguage());
989
+ var lang = getLanguage();
990
+ var translations = getTranslations(lang);
757
991
  // Whitelist-sanitize before interpolating into innerHTML downstream, matching
758
992
  // the user-input path in handleMultiPlanInput so all entry points share the
759
993
  // same trust posture regardless of how the caller sourced rawPrice.
@@ -769,7 +1003,7 @@ function resetMultiPlanModal(modalNode, rawPrice, opts) {
769
1003
  if (container) container.classList.remove('input-error');
770
1004
  renderDynamicSections(modalNode, currency, priceString, _objectSpread$3(_objectSpread$3({}, opts), {}, {
771
1005
  minPrice: 0
772
- }), translations);
1006
+ }), translations, lang);
773
1007
  }
774
1008
  function getMultiPlanModal(modalNode, priceString, opts) {
775
1009
  var currentLang = getLanguage();
@@ -789,7 +1023,7 @@ function getMultiPlanModal(modalNode, priceString, opts) {
789
1023
  minPrice: 0
790
1024
  }));
791
1025
  modalNode.className = 'sezzle-checkout-modal-lightbox sezzle-modal';
792
- var modalContent = "<section class=\"sezzle-checkout-modal-lightbox close-sezzle-modal\" lang=\"".concat(currentLang, "\" aria-label=\"").concat(translations.sezzleInformation, "\" style=\"display: block;\">\n <div id=\"sezzle-modal-container\" role=\"dialog\" aria-label=\"Sezzle Modal\" class=\"sezzle-checkout-modal-hidden sezzle-multi-plan").concat(eligibility.pi5 ? '' : ' pi4-only', "\">\n <div class=\"sezzle-modal\">\n <div><button role=\"button\" aria-label=\"").concat(translations.closeSezzleModal, "\" class=\"close-sezzle-modal\"></button></div>\n <div class=\"sezzle-logo\" title=\"Sezzle\"></div>\n <div id=\"sezzle-modal-core-content\" class=\"sezzle-modal-content\">\n <p class='trusted'>").concat(translations.MultiPlantrusted, "</p>\n <header class='sezzle-header'>").concat(translations.MultiPlanheader, "</header>\n <div class='payment-plan-wrapper'>\n <p class='sample-payments ").concat(currentLang === 'fr' ? 'sezzle-multi-plan-fr' : '', "'>\n <span class=\"sample-payments-title\">").concat(translations.MultiPlanSeePlans, "</span>\n <span class=\"input-amount-container\">\n <label class=\"input-amount-label\" for=\"multi-plan-input-amount\">").concat(translations.MultiPlanAmount, "</label>\n <input class='price input-amount' id=\"multi-plan-input-amount\" maxlength=\"12\" value='").concat(currency + priceString, "'/>\n </span>\n </p>\n <div class='payment-cards payment-cards-biweekly'").concat(eligibility.pi4 ? '' : ' style="display:none"', ">").concat(generateBiweeklyInner(eligibility, currency, priceString, opts, translations), "</div>\n <div class='payment-cards payment-cards-monthly'").concat(eligibility.lt ? '' : ' style="display:none"', ">").concat(generateMonthlyInner(eligibility, currency, priceString, opts, translations), "</div>\n </div>\n <div class='how-to-sezzle'>\n <div class='carousel-header'>\n <div class='how-to-text-wrapper'>\n <span class='how-to-text'>").concat(translations.MultiPlanhowToPay, "</span>\n <div class='how-to-logo'>\n <img class=\"how-to-sezzle-logo szl-light-image\" src=\"https://media.sezzle.com/branding/2.0/Sezzle_Logo_FullColor.svg\" alt=\"Sezzle\" style=\"height: 14px; width: 58px;\">\n </div>\n </div>\n <div class='arrows'>\n <button type='button' class='arrow arrow-left disabled' disabled aria-label='").concat(translations.previousSlide, "'>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M14.5 16.4078C14.825 16.0828 14.825 15.5578 14.5 15.2328L11.2667 11.9995L14.5 8.76614C14.825 8.44114 14.825 7.91614 14.5 7.59114C14.175 7.26614 13.65 7.26614 13.325 7.59114L9.5 11.4161C9.175 11.7411 9.175 12.2661 9.5 12.5911L13.325 16.4161C13.6417 16.7328 14.175 16.7328 14.5 16.4078Z\" fill=\"#8333D4\"/></svg>\n </button>\n <button type='button' class='arrow arrow-right' aria-label='").concat(translations.nextSlide, "'>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 7.59219C9.175 7.91719 9.175 8.44219 9.5 8.76719L12.7333 12.0005L9.5 15.2339C9.175 15.5589 9.175 16.0839 9.5 16.4089C9.825 16.7339 10.35 16.7339 10.675 16.4089L14.5 12.5839C14.825 12.2589 14.825 11.7339 14.5 11.4089L10.675 7.58386C10.3583 7.26719 9.825 7.26719 9.5 7.59219Z\" fill=\"#8333D4\"/></svg>\n </button>\n </div>\n </div>\n <div class='carousel position-1'>\n <div class='carousel-item'><div class='carousel-item-content'><div class='step-number'><span class='step-number-content'>1</span></div><div class='step-name'>").concat(translations.MultiPlanStep1, "</div></div></div>\n <div class='carousel-item'><div class='carousel-item-content'><div class='step-number'><span class='step-number-content'>2</span></div><div class='step-name'>").concat(translations.MultiPlanStep2, "</div></div></div>\n <div class='carousel-item'><div class='carousel-item-content'><div class='step-number'><span class='step-number-content'>3</span></div><div class='step-name'>").concat(translations.MultiPlanStep3, "</div></div></div>\n </div>\n <div class='carousel-dots' role=\"tablist\" aria-label=\"").concat(translations.carouselPosition, "\">\n <div class=\"dot active\" role=\"tab\" aria-selected=\"true\" aria-label=\"").concat(translations.slide, " 1\"><svg width=\"6\" height=\"6\" viewBox=\"0 0 6 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><rect width=\"6\" height=\"6\" rx=\"3\" fill=\"#8333D4\"/></svg></div>\n <div class=\"dot\" role=\"tab\" aria-selected=\"false\" aria-label=\"").concat(translations.slide, " 2\"><svg width=\"6\" height=\"6\" viewBox=\"0 0 6 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><rect width=\"6\" height=\"6\" rx=\"3\" fill=\"#8333D4\"/></svg></div>\n <div class=\"dot\" role=\"tab\" aria-selected=\"false\" aria-label=\"").concat(translations.slide, " 3\"><svg width=\"6\" height=\"6\" viewBox=\"0 0 6 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><rect width=\"6\" height=\"6\" rx=\"3\" fill=\"#8333D4\"/></svg></div>\n </div>\n </div>\n <div class=\"terms-container\">").concat(generateTermsInner(eligibility, translations), "</div>\n </div>\n </div>\n </div>\n</section>");
1026
+ var modalContent = "<section class=\"sezzle-checkout-modal-lightbox close-sezzle-modal\" lang=\"".concat(currentLang, "\" aria-label=\"").concat(translations.sezzleInformation, "\" style=\"display: block;\">\n <div id=\"sezzle-modal-container\" role=\"dialog\" aria-label=\"Sezzle Modal\" class=\"sezzle-checkout-modal-hidden sezzle-multi-plan").concat(eligibility.pi5 ? '' : ' pi4-only', "\">\n <div class=\"sezzle-modal\">\n <div><button role=\"button\" aria-label=\"").concat(translations.closeSezzleModal, "\" class=\"close-sezzle-modal\"></button></div>\n <div class=\"sezzle-logo\" title=\"Sezzle\"></div>\n <div id=\"sezzle-modal-core-content\" class=\"sezzle-modal-content\">\n <p class='trusted'>").concat(translations.MultiPlantrusted, "</p>\n <header class='sezzle-header'>").concat(translations.MultiPlanheader, "</header>\n <div class='payment-plan-wrapper'>\n <p class='sample-payments ").concat(currentLang === 'fr' ? 'sezzle-multi-plan-fr' : '', "'>\n <span class=\"sample-payments-title\">").concat(translations.MultiPlanSeePlans, "</span>\n <span class=\"input-amount-container\">\n <label class=\"input-amount-label\" for=\"multi-plan-input-amount\">").concat(translations.MultiPlanAmount, "</label>\n <input class='price input-amount' id=\"multi-plan-input-amount\" maxlength=\"12\" value='").concat(currency + priceString, "'/>\n </span>\n </p>\n <div class='payment-cards payment-cards-biweekly'").concat(eligibility.pi4 ? '' : ' style="display:none"', ">").concat(generateBiweeklyInner(eligibility, currency, priceString, opts, translations), "</div>\n <div class='payment-cards payment-cards-monthly'").concat(eligibility.lt ? '' : ' style="display:none"', ">").concat(generateMonthlyInner(eligibility, currency, priceString, opts, translations, currentLang), "</div>\n </div>\n <div class='how-to-sezzle'>\n <div class='carousel-header'>\n <div class='how-to-text-wrapper'>\n <span class='how-to-text'>").concat(translations.MultiPlanhowToPay, "</span>\n <div class='how-to-logo'>\n <img class=\"how-to-sezzle-logo szl-light-image\" src=\"https://media.sezzle.com/branding/2.0/Sezzle_Logo_FullColor.svg\" alt=\"Sezzle\" style=\"height: 14px; width: 58px;\">\n </div>\n </div>\n <div class='arrows'>\n <button type='button' class='arrow arrow-left disabled' disabled aria-label='").concat(translations.previousSlide, "'>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M14.5 16.4078C14.825 16.0828 14.825 15.5578 14.5 15.2328L11.2667 11.9995L14.5 8.76614C14.825 8.44114 14.825 7.91614 14.5 7.59114C14.175 7.26614 13.65 7.26614 13.325 7.59114L9.5 11.4161C9.175 11.7411 9.175 12.2661 9.5 12.5911L13.325 16.4161C13.6417 16.7328 14.175 16.7328 14.5 16.4078Z\" fill=\"#8333D4\"/></svg>\n </button>\n <button type='button' class='arrow arrow-right' aria-label='").concat(translations.nextSlide, "'>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 7.59219C9.175 7.91719 9.175 8.44219 9.5 8.76719L12.7333 12.0005L9.5 15.2339C9.175 15.5589 9.175 16.0839 9.5 16.4089C9.825 16.7339 10.35 16.7339 10.675 16.4089L14.5 12.5839C14.825 12.2589 14.825 11.7339 14.5 11.4089L10.675 7.58386C10.3583 7.26719 9.825 7.26719 9.5 7.59219Z\" fill=\"#8333D4\"/></svg>\n </button>\n </div>\n </div>\n <div class='carousel position-1'>\n <div class='carousel-item'><div class='carousel-item-content'><div class='step-number'><span class='step-number-content'>1</span></div><div class='step-name'>").concat(translations.MultiPlanStep1, "</div></div></div>\n <div class='carousel-item'><div class='carousel-item-content'><div class='step-number'><span class='step-number-content'>2</span></div><div class='step-name'>").concat(translations.MultiPlanStep2, "</div></div></div>\n <div class='carousel-item'><div class='carousel-item-content'><div class='step-number'><span class='step-number-content'>3</span></div><div class='step-name'>").concat(translations.MultiPlanStep3, "</div></div></div>\n </div>\n <div class='carousel-dots' role=\"tablist\" aria-label=\"").concat(translations.carouselPosition, "\">\n <div class=\"dot active\" role=\"tab\" aria-selected=\"true\" aria-label=\"").concat(translations.slide, " 1\"><svg width=\"6\" height=\"6\" viewBox=\"0 0 6 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><rect width=\"6\" height=\"6\" rx=\"3\" fill=\"#8333D4\"/></svg></div>\n <div class=\"dot\" role=\"tab\" aria-selected=\"false\" aria-label=\"").concat(translations.slide, " 2\"><svg width=\"6\" height=\"6\" viewBox=\"0 0 6 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><rect width=\"6\" height=\"6\" rx=\"3\" fill=\"#8333D4\"/></svg></div>\n <div class=\"dot\" role=\"tab\" aria-selected=\"false\" aria-label=\"").concat(translations.slide, " 3\"><svg width=\"6\" height=\"6\" viewBox=\"0 0 6 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><rect width=\"6\" height=\"6\" rx=\"3\" fill=\"#8333D4\"/></svg></div>\n </div>\n </div>\n <div class=\"terms-container\">").concat(generateTermsInner(eligibility, translations, opts, currentLang), "</div>\n </div>\n </div>\n </div>\n</section>");
793
1027
  modalNode.innerHTML = modalContent;
794
1028
  handleCarousel(modalNode);
795
1029
  if (eligibility.lt) attachFeaturesAccordion(modalNode);
@@ -841,7 +1075,10 @@ var Modal = /*#__PURE__*/function (_React$Component) {
841
1075
  maxPrice: _this.props.maxPrice,
842
1076
  minPriceLT: _this.props.minPriceLT,
843
1077
  maxPriceLT: _this.props.maxPriceLT,
844
- bestAPR: _this.props.bestAPR,
1078
+ minAPR: _this.props.minAPR,
1079
+ medianAPR: _this.props.medianAPR,
1080
+ maxAPR: _this.props.maxAPR,
1081
+ termsToShow: _this.props.termsToShow,
845
1082
  numberOfPayments: _this.props.numberOfPayments
846
1083
  });
847
1084
  handleCarousel(_this.state.modalElement);
@@ -911,7 +1148,10 @@ var Modal = /*#__PURE__*/function (_React$Component) {
911
1148
  maxPrice: props.maxPrice,
912
1149
  minPriceLT: props.minPriceLT,
913
1150
  maxPriceLT: props.maxPriceLT,
914
- bestAPR: props.bestAPR,
1151
+ minAPR: props.minAPR,
1152
+ medianAPR: props.medianAPR,
1153
+ maxAPR: props.maxAPR,
1154
+ termsToShow: props.termsToShow,
915
1155
  numberOfPayments: props.numberOfPayments
916
1156
  });
917
1157
  }
@@ -934,7 +1174,10 @@ Modal.propTypes = {
934
1174
  maxPrice: PropTypes__default["default"].number,
935
1175
  minPriceLT: PropTypes__default["default"].number,
936
1176
  maxPriceLT: PropTypes__default["default"].number,
937
- bestAPR: PropTypes__default["default"].number
1177
+ minAPR: PropTypes__default["default"].number,
1178
+ medianAPR: PropTypes__default["default"].number,
1179
+ maxAPR: PropTypes__default["default"].number,
1180
+ termsToShow: PropTypes__default["default"].object
938
1181
  };
939
1182
 
940
1183
  function _typeof$1(o) { "@babel/helpers - typeof"; return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof$1(o); }
@@ -1013,7 +1256,7 @@ var SezzleWidgetText = /*#__PURE__*/function (_React$Component) {
1013
1256
  var priceElement = /*#__PURE__*/React__default["default"].createElement("span", {
1014
1257
  className: "sezzle-payment-amount sezzle-button-text",
1015
1258
  key: index
1016
- }, getFormattedPrice(_this2.state.config.price, effectiveNumberOfPayments, _this2.state.config.minPriceLT, _this2.state.config.maxPriceLT, _this2.state.config.bestAPR));
1259
+ }, getFormattedPrice(_this2.state.config.price, effectiveNumberOfPayments, _this2.state.config.minPriceLT, _this2.state.config.maxPriceLT, _this2.state.config.medianAPR, _this2.state.config.termsToShow));
1017
1260
  subtemplates.push(priceElement);
1018
1261
  break;
1019
1262
  case 'logo':
@@ -1138,7 +1381,10 @@ var SezzleWidgetText = /*#__PURE__*/function (_React$Component) {
1138
1381
  maxPrice: _this3.state.config.maxPrice,
1139
1382
  minPriceLT: _this3.state.config.minPriceLT,
1140
1383
  maxPriceLT: _this3.state.config.maxPriceLT,
1141
- bestAPR: _this3.state.config.bestAPR,
1384
+ minAPR: _this3.state.config.minAPR,
1385
+ medianAPR: _this3.state.config.medianAPR,
1386
+ maxAPR: _this3.state.config.maxAPR,
1387
+ termsToShow: _this3.state.config.termsToShow,
1142
1388
  price: _this3.state.config.price,
1143
1389
  numberOfPayments: _this3.state.config.numberOfPayments
1144
1390
  });
@@ -1180,6 +1426,18 @@ var SezzleWidgetWrapper = /*#__PURE__*/function (_React$Component) {
1180
1426
  var _this;
1181
1427
  _classCallCheck(this, SezzleWidgetWrapper);
1182
1428
  _this = _callSuper(this, SezzleWidgetWrapper, [props]);
1429
+ // Resolve LT options from the LTgroup alias preset, overlaid with any
1430
+ // explicitly-set LT props. Returns a fully-disabled config when neither
1431
+ // LTgroup nor minPriceLT is provided.
1432
+ var ltConfig = resolveLTConfig({
1433
+ LTgroup: _this.props.LTgroup,
1434
+ minPriceLT: _this.props.minPriceLT,
1435
+ maxPriceLT: _this.props.maxPriceLT,
1436
+ minAPR: _this.props.minAPR,
1437
+ medianAPR: _this.props.medianAPR,
1438
+ maxAPR: _this.props.maxAPR,
1439
+ termsToShow: _this.props.termsToShow
1440
+ });
1183
1441
  _this.state = {
1184
1442
  sezzleConfig: {
1185
1443
  price: _this.props.price || 0,
@@ -1187,9 +1445,12 @@ var SezzleWidgetWrapper = /*#__PURE__*/function (_React$Component) {
1187
1445
  includeAPModal: _this.props.includeAPModal || false,
1188
1446
  minPrice: _this.props.minPrice || 0,
1189
1447
  maxPrice: _this.props.maxPrice || 2500,
1190
- minPriceLT: _this.props.minPriceLT || 0,
1191
- maxPriceLT: _this.props.maxPriceLT || 15000,
1192
- bestAPR: _this.props.bestAPR || 21.99,
1448
+ minPriceLT: ltConfig.minPriceLT,
1449
+ maxPriceLT: ltConfig.maxPriceLT,
1450
+ minAPR: ltConfig.minAPR,
1451
+ medianAPR: ltConfig.medianAPR,
1452
+ maxAPR: ltConfig.maxAPR,
1453
+ termsToShow: ltConfig.termsToShow,
1193
1454
  theme: _this.props.theme || 'light',
1194
1455
  alignment: _this.props.alignment || 'auto',
1195
1456
  fontWeight: _this.props.fontWeight || 500,
@@ -1239,9 +1500,13 @@ SezzleWidgetWrapper.propTypes = {
1239
1500
  logoSize: PropTypes__default["default"].number,
1240
1501
  minPrice: PropTypes__default["default"].number,
1241
1502
  maxPrice: PropTypes__default["default"].number,
1503
+ LTgroup: PropTypes__default["default"].string,
1242
1504
  minPriceLT: PropTypes__default["default"].number,
1243
1505
  maxPriceLT: PropTypes__default["default"].number,
1244
- bestAPR: PropTypes__default["default"].number,
1506
+ minAPR: PropTypes__default["default"].number,
1507
+ medianAPR: PropTypes__default["default"].number,
1508
+ maxAPR: PropTypes__default["default"].number,
1509
+ termsToShow: PropTypes__default["default"].object,
1245
1510
  includeAPModal: PropTypes__default["default"].bool,
1246
1511
  numberOfPayments: PropTypes__default["default"].number
1247
1512
  };