@schematichq/schematic-components 2.20.0 → 2.21.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.
@@ -5052,6 +5052,9 @@ var en_default = {
5052
5052
  "After the trial, subscribe": "After the trial, subscription starts and you will be billed.",
5053
5053
  Agreement: "Agreement",
5054
5054
  "Amount off": "{{amount}} off",
5055
+ "Applied balance towards next invoice": "Applied balance towards next invoice",
5056
+ "Discount for months_one": "{{discount}} for next month",
5057
+ "Discount for months_other": "{{discount}} for next {{count}} months",
5055
5058
  "Auto Top-up": "Auto top-up",
5056
5059
  "Auto top-up enabled": "Auto top-up enabled",
5057
5060
  "Auto top-up disabled": "Auto top-up disabled",
@@ -5147,7 +5150,7 @@ var en_default = {
5147
5150
  Proration: "Proration",
5148
5151
  Quantity: "Quantity",
5149
5152
  "Quantity to pay for in advance": "Quantity to pay for in advance",
5150
- "Remaining balance": "Remaining balance",
5153
+ "Remaining balance after next invoice": "Remaining balance after next invoice",
5151
5154
  Remove: "Remove",
5152
5155
  "Remove add-on": "Remove add-on",
5153
5156
  Resets: "Resets {{date}}",
@@ -5222,6 +5225,14 @@ var en_default = {
5222
5225
  "X units per use": "{{amount}} {{units}} per use",
5223
5226
  "X time left in trial": "{{amount}} {{units}} left in trial",
5224
5227
  "Yearly total": "Yearly total",
5228
+ "You will be billed": "You will be billed {{price}} {{usage}}for this subscription every {{period}} {{schedule}}unless you unsubscribe.",
5229
+ "You will be billed with discount window": "You will be billed {{price}} {{usage}}for this subscription every {{period}} {{schedule}}{{window}}, then {{fullPrice}} every {{period}} afterward, unless you unsubscribe.",
5230
+ "You will be billed next bill discount": "You will be billed {{price}} {{usage}}for this subscription on your next bill, then {{fullPrice}} every {{period}} {{schedule}}afterward, unless you unsubscribe.",
5231
+ "plus usage based costs": "plus usage based costs",
5232
+ "on the day": "on the {{day}}",
5233
+ "of month": "of {{month}}",
5234
+ "for the next months_one": "for the next month",
5235
+ "for the next months_other": "for the next {{count}} months",
5225
5236
  "You will be downgraded at the end of your billing period.": "You will be downgraded to the {{plan}} plan at the end of your billing period on {{date}}.",
5226
5237
  "You will retain access to your plan until the end of the billing period, on": "You will retain access to your plan until the end of the billing period, on",
5227
5238
  "$X per unit": "{{cost}} per {{unit}}",
@@ -5909,7 +5920,7 @@ var i;
5909
5920
  var c = "undefined" != typeof process && void 0 !== process.env && (process.env.REACT_APP_SC_ATTR || process.env.SC_ATTR) || "data-styled";
5910
5921
  var a = "active";
5911
5922
  var l = "data-styled-version";
5912
- var u = "6.4.3";
5923
+ var u = "6.4.4";
5913
5924
  var h = "/*!sc*/\n";
5914
5925
  var d = "undefined" != typeof window && "undefined" != typeof document;
5915
5926
  function p(e2) {
@@ -8317,6 +8328,20 @@ function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
8317
8328
  return json;
8318
8329
  }
8319
8330
 
8331
+ // src/api/checkoutexternal/models/WarningTier.ts
8332
+ function WarningTierFromJSON(json) {
8333
+ return WarningTierFromJSONTyped(json, false);
8334
+ }
8335
+ function WarningTierFromJSONTyped(json, ignoreDiscriminator) {
8336
+ if (json == null) {
8337
+ return json;
8338
+ }
8339
+ return {
8340
+ key: json["key"],
8341
+ value: json["value"]
8342
+ };
8343
+ }
8344
+
8320
8345
  // src/api/checkoutexternal/models/FeatureEntitlement.ts
8321
8346
  function FeatureEntitlementFromJSON(json) {
8322
8347
  return FeatureEntitlementFromJSONTyped(json, false);
@@ -8343,7 +8368,8 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
8343
8368
  monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
8344
8369
  softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
8345
8370
  usage: json["usage"] == null ? void 0 : json["usage"],
8346
- valueType: EntitlementValueTypeFromJSON(json["value_type"])
8371
+ valueType: EntitlementValueTypeFromJSON(json["value_type"]),
8372
+ warningTiers: json["warning_tiers"] == null ? void 0 : json["warning_tiers"].map(WarningTierFromJSON)
8347
8373
  };
8348
8374
  }
8349
8375
 
@@ -8690,6 +8716,7 @@ function CompanyOverrideNoteResponseDataFromJSONTyped(json, ignoreDiscriminator)
8690
8716
  var FeatureType = {
8691
8717
  Boolean: "boolean",
8692
8718
  Event: "event",
8719
+ License: "license",
8693
8720
  Trait: "trait"
8694
8721
  };
8695
8722
  function FeatureTypeFromJSON(json) {
@@ -8722,13 +8749,15 @@ function FeatureResponseDataFromJSONTyped(json, ignoreDiscriminator) {
8722
8749
  featureType: FeatureTypeFromJSON(json["feature_type"]),
8723
8750
  icon: json["icon"],
8724
8751
  id: json["id"],
8752
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
8725
8753
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON(json["lifecycle_phase"]),
8726
8754
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
8727
8755
  name: json["name"],
8728
8756
  pluralName: json["plural_name"] == null ? void 0 : json["plural_name"],
8729
8757
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
8730
8758
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
8731
- updatedAt: new Date(json["updated_at"])
8759
+ updatedAt: new Date(json["updated_at"]),
8760
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
8732
8761
  };
8733
8762
  }
8734
8763
 
@@ -9080,6 +9109,7 @@ function FeatureInPlanResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9080
9109
  flags: json["flags"].map(FlagInPlanResponseDataFromJSON),
9081
9110
  icon: json["icon"],
9082
9111
  id: json["id"],
9112
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
9083
9113
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON(json["lifecycle_phase"]),
9084
9114
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
9085
9115
  name: json["name"],
@@ -9088,7 +9118,8 @@ function FeatureInPlanResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9088
9118
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
9089
9119
  trait: json["trait"] == null ? void 0 : EntityTraitDefinitionResponseDataFromJSON(json["trait"]),
9090
9120
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
9091
- updatedAt: new Date(json["updated_at"])
9121
+ updatedAt: new Date(json["updated_at"]),
9122
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
9092
9123
  };
9093
9124
  }
9094
9125
 
@@ -9165,6 +9196,20 @@ function PlanCreditGrantViewFromJSONTyped(json, ignoreDiscriminator) {
9165
9196
  };
9166
9197
  }
9167
9198
 
9199
+ // src/api/checkoutexternal/models/PlanCatalogMembershipResponseData.ts
9200
+ function PlanCatalogMembershipResponseDataFromJSON(json) {
9201
+ return PlanCatalogMembershipResponseDataFromJSONTyped(json, false);
9202
+ }
9203
+ function PlanCatalogMembershipResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9204
+ if (json == null) {
9205
+ return json;
9206
+ }
9207
+ return {
9208
+ id: json["id"],
9209
+ name: json["name"]
9210
+ };
9211
+ }
9212
+
9168
9213
  // src/api/checkoutexternal/models/PlanCurrencyPricesResponseData.ts
9169
9214
  function PlanCurrencyPricesResponseDataFromJSON(json) {
9170
9215
  return PlanCurrencyPricesResponseDataFromJSONTyped(json, false);
@@ -9321,6 +9366,9 @@ function CompanyPlanDetailResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9321
9366
  ),
9322
9367
  billingProduct: json["billing_product"] == null ? void 0 : BillingProductDetailResponseDataFromJSON(json["billing_product"]),
9323
9368
  billingStrategy: BillingStrategyFromJSON(json["billing_strategy"]),
9369
+ catalogs: json["catalogs"] == null ? void 0 : json["catalogs"].map(
9370
+ PlanCatalogMembershipResponseDataFromJSON
9371
+ ),
9324
9372
  chargeType: ChargeTypeFromJSON(json["charge_type"]),
9325
9373
  companyCanTrial: json["company_can_trial"],
9326
9374
  companyCount: json["company_count"],
@@ -9494,6 +9542,9 @@ function PlanDetailResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9494
9542
  ),
9495
9543
  billingProduct: json["billing_product"] == null ? void 0 : BillingProductDetailResponseDataFromJSON(json["billing_product"]),
9496
9544
  billingStrategy: BillingStrategyFromJSON(json["billing_strategy"]),
9545
+ catalogs: json["catalogs"] == null ? void 0 : json["catalogs"].map(
9546
+ PlanCatalogMembershipResponseDataFromJSON
9547
+ ),
9497
9548
  chargeType: ChargeTypeFromJSON(json["charge_type"]),
9498
9549
  companyCount: json["company_count"],
9499
9550
  companyId: json["company_id"] == null ? void 0 : json["company_id"],
@@ -9663,6 +9714,7 @@ function ComponentResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9663
9714
  }
9664
9715
  return {
9665
9716
  ast: json["ast"] == null ? void 0 : json["ast"],
9717
+ catalogId: json["catalog_id"] == null ? void 0 : json["catalog_id"],
9666
9718
  createdAt: new Date(json["created_at"]),
9667
9719
  id: json["id"],
9668
9720
  name: json["name"],
@@ -9899,6 +9951,29 @@ function PreviewSubscriptionUpcomingInvoiceLineItemsFromJSONTyped(json, ignoreDi
9899
9951
  };
9900
9952
  }
9901
9953
 
9954
+ // src/api/checkoutexternal/models/PreviewSubscriptionDiscountResponseData.ts
9955
+ function PreviewSubscriptionDiscountResponseDataFromJSON(json) {
9956
+ return PreviewSubscriptionDiscountResponseDataFromJSONTyped(json, false);
9957
+ }
9958
+ function PreviewSubscriptionDiscountResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9959
+ if (json == null) {
9960
+ return json;
9961
+ }
9962
+ return {
9963
+ amountOff: json["amount_off"] == null ? void 0 : json["amount_off"],
9964
+ couponName: json["coupon_name"],
9965
+ currency: json["currency"] == null ? void 0 : json["currency"],
9966
+ customerFacingCode: json["customer_facing_code"] == null ? void 0 : json["customer_facing_code"],
9967
+ duration: json["duration"],
9968
+ durationInMonths: json["duration_in_months"] == null ? void 0 : json["duration_in_months"],
9969
+ endedAt: json["ended_at"] == null ? void 0 : new Date(json["ended_at"]),
9970
+ isActive: json["is_active"],
9971
+ percentOff: json["percent_off"] == null ? void 0 : json["percent_off"],
9972
+ promoCodeExternalId: json["promo_code_external_id"] == null ? void 0 : json["promo_code_external_id"],
9973
+ startedAt: new Date(json["started_at"])
9974
+ };
9975
+ }
9976
+
9902
9977
  // src/api/checkoutexternal/models/PreviewSubscriptionFinanceResponseData.ts
9903
9978
  function PreviewSubscriptionFinanceResponseDataFromJSON(json) {
9904
9979
  return PreviewSubscriptionFinanceResponseDataFromJSONTyped(json, false);
@@ -9909,6 +9984,9 @@ function PreviewSubscriptionFinanceResponseDataFromJSONTyped(json, ignoreDiscrim
9909
9984
  }
9910
9985
  return {
9911
9986
  amountOff: json["amount_off"],
9987
+ discounts: json["discounts"].map(
9988
+ PreviewSubscriptionDiscountResponseDataFromJSON
9989
+ ),
9912
9990
  dueNow: json["due_now"],
9913
9991
  newCharges: json["new_charges"],
9914
9992
  percentOff: json["percent_off"],
@@ -11526,13 +11604,15 @@ function FeatureResponseDataFromJSONTyped5(json, ignoreDiscriminator) {
11526
11604
  featureType: FeatureTypeFromJSON2(json["feature_type"]),
11527
11605
  icon: json["icon"],
11528
11606
  id: json["id"],
11607
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
11529
11608
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON2(json["lifecycle_phase"]),
11530
11609
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
11531
11610
  name: json["name"],
11532
11611
  pluralName: json["plural_name"] == null ? void 0 : json["plural_name"],
11533
11612
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
11534
11613
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
11535
- updatedAt: new Date(json["updated_at"])
11614
+ updatedAt: new Date(json["updated_at"]),
11615
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
11536
11616
  };
11537
11617
  }
11538
11618
 
@@ -11589,6 +11669,7 @@ function FeatureInPlanResponseDataFromJSONTyped6(json, ignoreDiscriminator) {
11589
11669
  flags: json["flags"].map(FlagInPlanResponseDataFromJSON2),
11590
11670
  icon: json["icon"],
11591
11671
  id: json["id"],
11672
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
11592
11673
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON2(json["lifecycle_phase"]),
11593
11674
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
11594
11675
  name: json["name"],
@@ -11597,7 +11678,8 @@ function FeatureInPlanResponseDataFromJSONTyped6(json, ignoreDiscriminator) {
11597
11678
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
11598
11679
  trait: json["trait"] == null ? void 0 : EntityTraitDefinitionResponseDataFromJSON2(json["trait"]),
11599
11680
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
11600
- updatedAt: new Date(json["updated_at"])
11681
+ updatedAt: new Date(json["updated_at"]),
11682
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
11601
11683
  };
11602
11684
  }
11603
11685
 
@@ -11776,6 +11858,20 @@ function PlanCreditGrantViewFromJSONTyped3(json, ignoreDiscriminator) {
11776
11858
  };
11777
11859
  }
11778
11860
 
11861
+ // src/api/componentspublic/models/PlanCatalogMembershipResponseData.ts
11862
+ function PlanCatalogMembershipResponseDataFromJSON2(json) {
11863
+ return PlanCatalogMembershipResponseDataFromJSONTyped5(json, false);
11864
+ }
11865
+ function PlanCatalogMembershipResponseDataFromJSONTyped5(json, ignoreDiscriminator) {
11866
+ if (json == null) {
11867
+ return json;
11868
+ }
11869
+ return {
11870
+ id: json["id"],
11871
+ name: json["name"]
11872
+ };
11873
+ }
11874
+
11779
11875
  // src/api/componentspublic/models/PlanCurrencyPricesResponseData.ts
11780
11876
  function PlanCurrencyPricesResponseDataFromJSON2(json) {
11781
11877
  return PlanCurrencyPricesResponseDataFromJSONTyped5(json, false);
@@ -11843,6 +11939,9 @@ function PlanViewPublicResponseDataFromJSONTyped(json, ignoreDiscriminator) {
11843
11939
  ),
11844
11940
  billingProduct: json["billing_product"] == null ? void 0 : BillingProductDetailResponseDataFromJSON2(json["billing_product"]),
11845
11941
  billingStrategy: BillingStrategyFromJSON2(json["billing_strategy"]),
11942
+ catalogs: json["catalogs"] == null ? void 0 : json["catalogs"].map(
11943
+ PlanCatalogMembershipResponseDataFromJSON2
11944
+ ),
11846
11945
  chargeType: ChargeTypeFromJSON2(json["charge_type"]),
11847
11946
  companyCount: json["company_count"],
11848
11947
  companyId: json["company_id"] == null ? void 0 : json["company_id"],
@@ -12460,7 +12559,7 @@ function getMetricPeriodName(entitlement) {
12460
12559
  const name = period ? PeriodName[period] : void 0;
12461
12560
  return name;
12462
12561
  }
12463
- function getUsageDetails(entitlement, period, currency) {
12562
+ function getUsageDetails(entitlement, period, currency, options) {
12464
12563
  const billingPrice = currency ? getEntitlementPrice(entitlement, period ?? "month", currency) : period === "year" ? entitlement.yearlyUsageBasedPrice : period === "quarter" ? entitlement.quarterlyUsageBasedPrice : period === "month" ? entitlement.monthlyUsageBasedPrice : void 0;
12465
12564
  let limit;
12466
12565
  if ((!entitlement.priceBehavior || entitlement.priceBehavior === EntitlementPriceBehavior.PayInAdvance) && typeof entitlement.allocation === "number") {
@@ -12508,8 +12607,21 @@ function getUsageDetails(entitlement, period, currency) {
12508
12607
  start = end + 1;
12509
12608
  }
12510
12609
  }
12610
+ if (options?.showWarningThresholdAsLimit) {
12611
+ const warningThreshold = getEntitlementWarningThreshold(
12612
+ entitlement.planEntitlement?.warningTiers
12613
+ );
12614
+ if (typeof warningThreshold === "number") {
12615
+ limit = warningThreshold;
12616
+ }
12617
+ }
12511
12618
  return { billingPrice, limit, amount, cost, currentTier };
12512
12619
  }
12620
+ var WARNING_TIER_DEFAULT_KEY = "default";
12621
+ function getEntitlementWarningThreshold(warningTiers) {
12622
+ const tier = warningTiers?.find((t3) => t3?.key === WARNING_TIER_DEFAULT_KEY);
12623
+ return typeof tier?.value === "number" ? tier.value : void 0;
12624
+ }
12513
12625
  function getCreditBasedEntitlementLimit(entitlement, credits) {
12514
12626
  const matchedCredit = credits.find(
12515
12627
  (credit) => credit.id === entitlement.valueCredit?.id
@@ -13057,85 +13169,6 @@ function modifyDate(date, days) {
13057
13169
  return copy3;
13058
13170
  }
13059
13171
 
13060
- // src/utils/error.ts
13061
- function isError(value) {
13062
- return value instanceof Error;
13063
- }
13064
- var ERROR_UNKNOWN = new Error("An unknown error occurred.");
13065
-
13066
- // src/utils/event.ts
13067
- var createKeyboardExecutionHandler = (fn) => {
13068
- const handler = (event) => {
13069
- if (event.key === "Enter" || event.key === " ") {
13070
- event.preventDefault();
13071
- fn?.(event);
13072
- }
13073
- };
13074
- return handler;
13075
- };
13076
-
13077
- // src/utils/markdown.tsx
13078
- var import_react14 = require("react");
13079
- var import_jsx_runtime2 = require("react/jsx-runtime");
13080
- var TOKEN = /(\[[^\]]+\]\([^)\s]+\))|(\*\*[^*]+\*\*)|(\*[^*]+\*)/g;
13081
- var LINK = /^\[([^\]]+)\]\(([^)\s]+)\)$/;
13082
- var isSafeUrl = (url) => {
13083
- try {
13084
- const { protocol } = new URL(url);
13085
- return protocol === "http:" || protocol === "https:";
13086
- } catch {
13087
- return false;
13088
- }
13089
- };
13090
- var renderOptInMarkdown = (text) => {
13091
- if (!text) {
13092
- return null;
13093
- }
13094
- const nodes = [];
13095
- let lastIndex = 0;
13096
- let key = 0;
13097
- TOKEN.lastIndex = 0;
13098
- let match2;
13099
- while ((match2 = TOKEN.exec(text)) !== null) {
13100
- if (match2.index > lastIndex) {
13101
- nodes.push(
13102
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react14.Fragment, { children: text.slice(lastIndex, match2.index) }, key++)
13103
- );
13104
- }
13105
- const [token2, link, bold, italic] = match2;
13106
- if (link) {
13107
- const parts = LINK.exec(link);
13108
- if (parts && isSafeUrl(parts[2])) {
13109
- nodes.push(
13110
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13111
- Text,
13112
- {
13113
- as: "a",
13114
- display: "link",
13115
- href: parts[2],
13116
- target: "_blank",
13117
- rel: "noopener noreferrer",
13118
- children: parts[1]
13119
- },
13120
- key++
13121
- )
13122
- );
13123
- } else {
13124
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react14.Fragment, { children: parts ? parts[1] : token2 }, key++));
13125
- }
13126
- } else if (bold) {
13127
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: bold.slice(2, -2) }, key++));
13128
- } else if (italic) {
13129
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("em", { children: italic.slice(1, -1) }, key++));
13130
- }
13131
- lastIndex = match2.index + token2.length;
13132
- }
13133
- if (lastIndex < text.length) {
13134
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react14.Fragment, { children: text.slice(lastIndex) }, key));
13135
- }
13136
- return nodes;
13137
- };
13138
-
13139
13172
  // src/utils/string.ts
13140
13173
  var ZERO_DECIMAL_CURRENCIES = /* @__PURE__ */ new Set([
13141
13174
  "BIF",
@@ -13284,6 +13317,168 @@ function getCurrencySymbol(currency) {
13284
13317
  }
13285
13318
  }
13286
13319
 
13320
+ // src/utils/discount.ts
13321
+ function getSubscriptionDiscount(discounts, subscriptionTotal, subscriptionCurrency) {
13322
+ const activeDiscounts = (discounts || []).filter(
13323
+ (discount2) => discount2.isActive && (typeof discount2.percentOff === "number" && discount2.percentOff > 0 || typeof discount2.amountOff === "number" && discount2.amountOff > 0)
13324
+ );
13325
+ if (activeDiscounts.length !== 1) {
13326
+ return void 0;
13327
+ }
13328
+ const discount = activeDiscounts[0];
13329
+ const isPercentOff = typeof discount.percentOff === "number" && discount.percentOff > 0;
13330
+ if (!isPercentOff && discount.currency && subscriptionCurrency && discount.currency.toLowerCase() !== subscriptionCurrency.toLowerCase()) {
13331
+ return void 0;
13332
+ }
13333
+ const discountedTotal = isPercentOff ? subscriptionTotal * (1 - discount.percentOff / 100) : Math.max(0, subscriptionTotal - (discount.amountOff ?? 0));
13334
+ if (discountedTotal >= subscriptionTotal) {
13335
+ return void 0;
13336
+ }
13337
+ return {
13338
+ duration: discount.duration,
13339
+ durationInMonths: discount.durationInMonths ?? void 0,
13340
+ discountedPrice: formatCurrency(
13341
+ discountedTotal,
13342
+ subscriptionCurrency ?? void 0
13343
+ )
13344
+ };
13345
+ }
13346
+ function getBillingPreviewText({
13347
+ subscriptionPrice,
13348
+ planPeriod,
13349
+ periodStart,
13350
+ hasUsageBasedCosts,
13351
+ discount
13352
+ }, t3) {
13353
+ if (!subscriptionPrice) {
13354
+ return null;
13355
+ }
13356
+ const usage = hasUsageBasedCosts ? `${t3("plus usage based costs")} ` : "";
13357
+ const scheduleParts = [];
13358
+ if (periodStart) {
13359
+ scheduleParts.push(
13360
+ t3("on the day", { day: formatOrdinal(periodStart.getDate()) })
13361
+ );
13362
+ }
13363
+ if (planPeriod === "year" && periodStart) {
13364
+ scheduleParts.push(t3("of month", { month: getMonthName(periodStart) }));
13365
+ }
13366
+ const schedule = scheduleParts.length > 0 ? `${scheduleParts.join(" ")} ` : "";
13367
+ if (!discount) {
13368
+ return t3("You will be billed", {
13369
+ price: subscriptionPrice,
13370
+ usage,
13371
+ period: planPeriod,
13372
+ schedule
13373
+ });
13374
+ }
13375
+ const { duration, durationInMonths, discountedPrice } = discount;
13376
+ if (duration === "forever") {
13377
+ return t3("You will be billed", {
13378
+ price: discountedPrice,
13379
+ usage,
13380
+ period: planPeriod,
13381
+ schedule
13382
+ });
13383
+ }
13384
+ if (duration === "repeating" && durationInMonths) {
13385
+ return t3("You will be billed with discount window", {
13386
+ price: discountedPrice,
13387
+ usage,
13388
+ period: planPeriod,
13389
+ schedule,
13390
+ window: t3("for the next months", { count: durationInMonths }),
13391
+ fullPrice: subscriptionPrice
13392
+ });
13393
+ }
13394
+ return t3("You will be billed next bill discount", {
13395
+ price: discountedPrice,
13396
+ usage,
13397
+ period: planPeriod,
13398
+ schedule,
13399
+ fullPrice: subscriptionPrice
13400
+ });
13401
+ }
13402
+
13403
+ // src/utils/error.ts
13404
+ function isError(value) {
13405
+ return value instanceof Error;
13406
+ }
13407
+ var ERROR_UNKNOWN = new Error("An unknown error occurred.");
13408
+
13409
+ // src/utils/event.ts
13410
+ var createKeyboardExecutionHandler = (fn) => {
13411
+ const handler = (event) => {
13412
+ if (event.key === "Enter" || event.key === " ") {
13413
+ event.preventDefault();
13414
+ fn?.(event);
13415
+ }
13416
+ };
13417
+ return handler;
13418
+ };
13419
+
13420
+ // src/utils/markdown.tsx
13421
+ var import_react14 = require("react");
13422
+ var import_jsx_runtime2 = require("react/jsx-runtime");
13423
+ var TOKEN = /(\[[^\]]+\]\([^)\s]+\))|(\*\*[^*]+\*\*)|(\*[^*]+\*)/g;
13424
+ var LINK = /^\[([^\]]+)\]\(([^)\s]+)\)$/;
13425
+ var isSafeUrl = (url) => {
13426
+ try {
13427
+ const { protocol } = new URL(url);
13428
+ return protocol === "http:" || protocol === "https:";
13429
+ } catch {
13430
+ return false;
13431
+ }
13432
+ };
13433
+ var renderOptInMarkdown = (text) => {
13434
+ if (!text) {
13435
+ return null;
13436
+ }
13437
+ const nodes = [];
13438
+ let lastIndex = 0;
13439
+ let key = 0;
13440
+ TOKEN.lastIndex = 0;
13441
+ let match2;
13442
+ while ((match2 = TOKEN.exec(text)) !== null) {
13443
+ if (match2.index > lastIndex) {
13444
+ nodes.push(
13445
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react14.Fragment, { children: text.slice(lastIndex, match2.index) }, key++)
13446
+ );
13447
+ }
13448
+ const [token2, link, bold, italic] = match2;
13449
+ if (link) {
13450
+ const parts = LINK.exec(link);
13451
+ if (parts && isSafeUrl(parts[2])) {
13452
+ nodes.push(
13453
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13454
+ Text,
13455
+ {
13456
+ as: "a",
13457
+ display: "link",
13458
+ href: parts[2],
13459
+ target: "_blank",
13460
+ rel: "noopener noreferrer",
13461
+ children: parts[1]
13462
+ },
13463
+ key++
13464
+ )
13465
+ );
13466
+ } else {
13467
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react14.Fragment, { children: parts ? parts[1] : token2 }, key++));
13468
+ }
13469
+ } else if (bold) {
13470
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: bold.slice(2, -2) }, key++));
13471
+ } else if (italic) {
13472
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("em", { children: italic.slice(1, -1) }, key++));
13473
+ }
13474
+ lastIndex = match2.index + token2.length;
13475
+ }
13476
+ if (lastIndex < text.length) {
13477
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react14.Fragment, { children: text.slice(lastIndex) }, key));
13478
+ }
13479
+ return nodes;
13480
+ };
13481
+
13287
13482
  // src/utils/style.ts
13288
13483
  function attr(key, value) {
13289
13484
  if (typeof value !== "undefined") {
@@ -13539,7 +13734,7 @@ var reducer = (state, action) => {
13539
13734
  // src/context/EmbedProvider.tsx
13540
13735
  var import_jsx_runtime3 = require("react/jsx-runtime");
13541
13736
  var getCustomHeaders = (sessionId) => ({
13542
- "X-Schematic-Components-Version": "2.20.0",
13737
+ "X-Schematic-Components-Version": "2.21.0",
13543
13738
  "X-Schematic-Session-ID": sessionId
13544
13739
  });
13545
13740
  var normalizeCurrencyFilter = (filter2) => {
@@ -13563,6 +13758,7 @@ var EmbedProvider = ({
13563
13758
  apiKey,
13564
13759
  apiConfig,
13565
13760
  currencyFilter,
13761
+ warningThresholdConfig,
13566
13762
  checkoutPrefill,
13567
13763
  ...options
13568
13764
  }) => {
@@ -13578,6 +13774,7 @@ var EmbedProvider = ({
13578
13774
  const providedState = {
13579
13775
  settings: opts.settings || {},
13580
13776
  currencyFilter: normalizeCurrencyFilter(currencyFilter),
13777
+ warningThresholdConfig,
13581
13778
  checkoutPrefill: normalizeCheckoutPrefill(checkoutPrefill)
13582
13779
  };
13583
13780
  const resolvedState = (0, import_merge2.default)({}, initialState, providedState);
@@ -14006,6 +14203,7 @@ var EmbedProvider = ({
14006
14203
  layout: state.layout,
14007
14204
  checkoutState: state.checkoutState,
14008
14205
  currencyFilter: state.currencyFilter,
14206
+ warningThresholdConfig: state.warningThresholdConfig,
14009
14207
  checkoutPrefill: state.checkoutPrefill,
14010
14208
  hydratePublic: debouncedHydratePublic,
14011
14209
  hydrate: debouncedHydrate,
@@ -15942,7 +16140,8 @@ var Entitlement = ({
15942
16140
  currency: selectedCurrency
15943
16141
  }) => {
15944
16142
  const { t: t3 } = useTranslation();
15945
- const { data, settings } = useEmbed();
16143
+ const { data, settings, warningThresholdConfig } = useEmbed();
16144
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
15946
16145
  const isLightBackground = useIsLightBackground();
15947
16146
  const showCredits = data?.displaySettings?.showCredits ?? true;
15948
16147
  const showFeatureDescription = data?.displaySettings?.showFeatureDescription ?? false;
@@ -15966,7 +16165,8 @@ var Entitlement = ({
15966
16165
  return;
15967
16166
  }
15968
16167
  const hasNumericValue = entitlement.valueType === EntitlementValueType.Numeric || entitlement.valueType === EntitlementValueType.Unlimited || entitlement.valueType === EntitlementValueType.Trait;
15969
- const limit = entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
16168
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
16169
+ const limit = typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
15970
16170
  const creditBasedEntitlementLimit = getCreditBasedEntitlementLimit(
15971
16171
  entitlement,
15972
16172
  credits
@@ -16059,7 +16259,8 @@ var Entitlement = ({
16059
16259
  currency,
16060
16260
  packageSize,
16061
16261
  tiered,
16062
- selectedCurrency
16262
+ selectedCurrency,
16263
+ showWarningThresholdAsLimit
16063
16264
  ]);
16064
16265
  const usageText = (0, import_react32.useMemo)(() => {
16065
16266
  if (!entitlement.feature) {
@@ -16790,7 +16991,8 @@ var AddOns = ({
16790
16991
  currency
16791
16992
  }) => {
16792
16993
  const { t: t3 } = useTranslation();
16793
- const { settings } = useEmbed();
16994
+ const { settings, warningThresholdConfig } = useEmbed();
16995
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
16794
16996
  const isLightBackground = useIsLightBackground();
16795
16997
  const periodKey = period === "year" ? "yearlyPrice" : period === "quarter" ? "quarterlyPrice" : "monthlyPrice";
16796
16998
  const cardPadding = settings.theme.card.padding / TEXT_BASE_SIZE;
@@ -16822,10 +17024,14 @@ var AddOns = ({
16822
17024
  period,
16823
17025
  currency
16824
17026
  );
17027
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
16825
17028
  return {
16826
17029
  isUnlimited: false,
16827
17030
  priceBehavior: entitlement.priceBehavior,
16828
17031
  softLimit: entitlement.softLimit,
17032
+ // The limit shown next to the feature: the warning threshold when
17033
+ // the option is on and one is configured, else the overage soft limit.
17034
+ limit: typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage ? entitlement.softLimit : void 0,
16829
17035
  price: priceData?.price ?? 0,
16830
17036
  currency: priceData?.currency || addOnCurrency,
16831
17037
  featureName: entitlement.feature?.name,
@@ -16974,7 +17180,7 @@ var AddOns = ({
16974
17180
  {
16975
17181
  $flexDirection: "column",
16976
17182
  $justifyContent: "center",
16977
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Text, { children: meteredEntitlement.priceBehavior === EntitlementPriceBehavior.Overage && meteredEntitlement.softLimit ? `${meteredEntitlement.softLimit} ${getEntitlementFeatureName(meteredEntitlement, "units")}` : getEntitlementFeatureName(meteredEntitlement) })
17183
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Text, { children: typeof meteredEntitlement.limit === "number" ? `${meteredEntitlement.limit} ${getEntitlementFeatureName(meteredEntitlement, "units")}` : getEntitlementFeatureName(meteredEntitlement) })
16978
17184
  }
16979
17185
  )
16980
17186
  ] }),
@@ -20259,7 +20465,7 @@ var SubscriptionSidebar = (0, import_react44.forwardRef)(
20259
20465
  );
20260
20466
  return { payAsYouGoEntitlements, payInAdvanceEntitlements: payInAdvanceEntitlements2 };
20261
20467
  }, [usageBasedEntitlements]);
20262
- const subscriptionPrice = (0, import_react44.useMemo)(() => {
20468
+ const { subscriptionPrice, subscriptionTotal, subscriptionCurrency } = (0, import_react44.useMemo)(() => {
20263
20469
  let planPrice;
20264
20470
  let resolvedCurrency;
20265
20471
  if (selectedPlan) {
@@ -20295,7 +20501,11 @@ var SubscriptionSidebar = (0, import_react44.forwardRef)(
20295
20501
  0
20296
20502
  );
20297
20503
  total += addOnPayInAdvanceCost;
20298
- return formatCurrency(total, resolvedCurrency);
20504
+ return {
20505
+ subscriptionPrice: formatCurrency(total, resolvedCurrency),
20506
+ subscriptionTotal: total,
20507
+ subscriptionCurrency: resolvedCurrency
20508
+ };
20299
20509
  }, [
20300
20510
  selectedPlan,
20301
20511
  currentPlan,
@@ -20422,6 +20632,14 @@ var SubscriptionSidebar = (0, import_react44.forwardRef)(
20422
20632
  () => promoCode && (amountOff > 0 || percentOff > 0),
20423
20633
  [promoCode, amountOff, percentOff]
20424
20634
  );
20635
+ const subscriptionDiscount = (0, import_react44.useMemo)(
20636
+ () => getSubscriptionDiscount(
20637
+ charges?.discounts,
20638
+ subscriptionTotal,
20639
+ subscriptionCurrency
20640
+ ),
20641
+ [charges?.discounts, subscriptionTotal, subscriptionCurrency]
20642
+ );
20425
20643
  const handleCheckout = (0, import_react44.useCallback)(async () => {
20426
20644
  const planId = selectedPlan?.id;
20427
20645
  const currencyPrice = selectedPlan ? getPlanPrice(
@@ -20668,6 +20886,16 @@ var SubscriptionSidebar = (0, import_react44.forwardRef)(
20668
20886
  if (isSelectedPlanTrialable && selectedPlan.trialDays) {
20669
20887
  trialEndsOn.setDate(trialEndsOn.getDate() + selectedPlan.trialDays);
20670
20888
  }
20889
+ const billingPreviewText = getBillingPreviewText(
20890
+ {
20891
+ subscriptionPrice,
20892
+ planPeriod,
20893
+ periodStart: renewDate,
20894
+ hasUsageBasedCosts: usageBasedEntitlements.length > 0,
20895
+ discount: subscriptionDiscount
20896
+ },
20897
+ t3
20898
+ );
20671
20899
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
20672
20900
  Flex,
20673
20901
  {
@@ -21216,9 +21444,7 @@ var SubscriptionSidebar = (0, import_react44.forwardRef)(
21216
21444
  }
21217
21445
  )
21218
21446
  }
21219
- ) : subscriptionPrice && // TODO: localize
21220
- `You will be billed ${subscriptionPrice} ${usageBasedEntitlements.length > 0 ? "plus usage based costs" : ""} for this subscription
21221
- every ${planPeriod} ${renewDate ? `on the ${formatOrdinal(renewDate.getDate())}` : ""} ${planPeriod === "year" && renewDate ? `of ${getMonthName(renewDate)}` : ""} unless you unsubscribe.` }) })
21447
+ ) : billingPreviewText }) })
21222
21448
  ]
21223
21449
  }
21224
21450
  )
@@ -21738,7 +21964,8 @@ var UsageDetails = ({ entitlement, layout }) => {
21738
21964
  metricResetAt
21739
21965
  } = entitlement;
21740
21966
  const { t: t3 } = useTranslation();
21741
- const { data } = useEmbed();
21967
+ const { data, warningThresholdConfig } = useEmbed();
21968
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
21742
21969
  const period = getSubscriptionPeriod(data?.company?.billingSubscription) ?? data?.company?.plan?.planPeriod ?? void 0;
21743
21970
  const showCredits = data?.displaySettings?.showCredits ?? true;
21744
21971
  const {
@@ -21754,7 +21981,9 @@ var UsageDetails = ({ entitlement, layout }) => {
21754
21981
  } = (0, import_react49.useMemo)(() => {
21755
21982
  const { billingPrice, amount, limit: limit2, cost: cost2, currentTier: currentTier2 } = getUsageDetails(
21756
21983
  entitlement,
21757
- period
21984
+ period,
21985
+ void 0,
21986
+ { showWarningThresholdAsLimit }
21758
21987
  );
21759
21988
  const {
21760
21989
  price: price2,
@@ -21775,7 +22004,7 @@ var UsageDetails = ({ entitlement, layout }) => {
21775
22004
  tiersMode: tiersMode2,
21776
22005
  tiered: priceBehavior === EntitlementPriceBehavior.PayInAdvance && isTieredPrice(billingPrice)
21777
22006
  };
21778
- }, [entitlement, period, priceBehavior]);
22007
+ }, [entitlement, period, priceBehavior, showWarningThresholdAsLimit]);
21779
22008
  const text = (0, import_react49.useMemo)(() => {
21780
22009
  if (!feature || feature.featureType !== FeatureType.Event && feature.featureType !== FeatureType.Trait) {
21781
22010
  return;
@@ -21825,9 +22054,10 @@ var UsageDetails = ({ entitlement, layout }) => {
21825
22054
  });
21826
22055
  }
21827
22056
  if (!priceBehavior && typeof allocation === "number") {
22057
+ const numericLimit = limit ?? allocation;
21828
22058
  return t3("X units", {
21829
- amount: formatNumber(allocation),
21830
- units: getFeatureName(feature, allocation)
22059
+ amount: formatNumber(numericLimit),
22060
+ units: getFeatureName(feature, numericLimit)
21831
22061
  });
21832
22062
  }
21833
22063
  if (!priceBehavior && allocationType === "unlimited") {
@@ -21913,7 +22143,7 @@ var UsageDetails = ({ entitlement, layout }) => {
21913
22143
  if (typeof usage === "number") {
21914
22144
  return typeof allocation === "number" ? t3("usage.limited", {
21915
22145
  amount: formatNumber(usage),
21916
- allocation: formatNumber(allocation)
22146
+ allocation: formatNumber(limit ?? allocation)
21917
22147
  }) : t3("usage.unlimited", {
21918
22148
  amount: formatNumber(usage)
21919
22149
  });
@@ -21927,6 +22157,7 @@ var UsageDetails = ({ entitlement, layout }) => {
21927
22157
  priceBehavior,
21928
22158
  packageSize,
21929
22159
  allocation,
22160
+ limit,
21930
22161
  usage,
21931
22162
  metricResetAt,
21932
22163
  cost,
@@ -22358,7 +22589,12 @@ var import_react52 = require("react");
22358
22589
  var import_jsx_runtime51 = require("react/jsx-runtime");
22359
22590
  var Meter = ({ entitlement }) => {
22360
22591
  const { allocation, priceBehavior, softLimit, usage } = entitlement;
22361
- const limit = softLimit ?? allocation;
22592
+ const { warningThresholdConfig } = useEmbed();
22593
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
22594
+ const warningThreshold = getEntitlementWarningThreshold(
22595
+ entitlement.planEntitlement?.warningTiers
22596
+ );
22597
+ const limit = showWarningThresholdAsLimit && typeof warningThreshold === "number" ? warningThreshold : softLimit ?? allocation;
22362
22598
  if (typeof usage !== "number" || typeof limit !== "number") {
22363
22599
  return null;
22364
22600
  }
@@ -22497,14 +22733,7 @@ var import_jsx_runtime53 = require("react/jsx-runtime");
22497
22733
  var Limit = ({ entitlement, usageDetails, fontStyle }) => {
22498
22734
  const { t: t3 } = useTranslation();
22499
22735
  const { data } = useEmbed();
22500
- const {
22501
- feature,
22502
- planEntitlement,
22503
- priceBehavior,
22504
- allocation,
22505
- usage,
22506
- metricResetAt
22507
- } = entitlement;
22736
+ const { feature, planEntitlement, priceBehavior, usage, metricResetAt } = entitlement;
22508
22737
  const { billingPrice, limit, cost, currentTier } = usageDetails;
22509
22738
  const acc = [];
22510
22739
  acc.push(
@@ -22526,8 +22755,8 @@ var Limit = ({ entitlement, usageDetails, fontStyle }) => {
22526
22755
  }) : priceBehavior === EntitlementPriceBehavior.CreditBurndown && typeof feature !== "undefined" && typeof limit === "number" ? t3("X units remaining", {
22527
22756
  amount: formatNumber(limit),
22528
22757
  units: getFeatureName(feature, limit)
22529
- }) : typeof allocation === "number" ? t3("Limit of", {
22530
- amount: formatNumber(allocation)
22758
+ }) : typeof limit === "number" ? t3("Limit of", {
22759
+ amount: formatNumber(limit)
22531
22760
  }) : t3("No limit")
22532
22761
  );
22533
22762
  if (metricResetAt) {
@@ -22582,7 +22811,8 @@ var MeteredFeatures = (0, import_react52.forwardRef)(({ className, ...rest }, re
22582
22811
  const elementsRef = (0, import_react52.useRef)([]);
22583
22812
  const shouldWrapChildren = useWrapChildren(elementsRef);
22584
22813
  const { t: t3 } = useTranslation();
22585
- const { data, settings, setCheckoutState } = useEmbed();
22814
+ const { data, settings, setCheckoutState, warningThresholdConfig } = useEmbed();
22815
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
22586
22816
  const isLightBackground = useIsLightBackground();
22587
22817
  const meteredFeatures = (0, import_react52.useMemo)(() => {
22588
22818
  const orderedFeatureUsage = props.visibleFeatures?.reduce(
@@ -22636,7 +22866,9 @@ var MeteredFeatures = (0, import_react52.forwardRef)(({ className, ...rest }, re
22636
22866
  return acc;
22637
22867
  }
22638
22868
  const { feature, priceBehavior, usage } = entitlement;
22639
- const usageDetails = getUsageDetails(entitlement, period);
22869
+ const usageDetails = getUsageDetails(entitlement, period, void 0, {
22870
+ showWarningThresholdAsLimit
22871
+ });
22640
22872
  const { limit } = usageDetails;
22641
22873
  acc.push(
22642
22874
  /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(Element, { as: Flex, $flexDirection: "column", $gap: "1.5rem", children: [
@@ -23254,7 +23486,7 @@ var registerWrapper = function registerWrapper2(stripe, startTime) {
23254
23486
  }
23255
23487
  stripe._registerWrapper({
23256
23488
  name: "stripe-js",
23257
- version: "9.9.0",
23489
+ version: "9.12.0",
23258
23490
  startTime
23259
23491
  });
23260
23492
  };
@@ -23332,7 +23564,7 @@ var initStripe = function initStripe2(maybeStripe, args, startTime) {
23332
23564
  var version = runtimeVersionToUrlVersion(maybeStripe.version);
23333
23565
  var expectedVersion = RELEASE_TRAIN;
23334
23566
  if (isTestKey && version !== expectedVersion) {
23335
- console.warn("Stripe.js@".concat(version, " was loaded on the page, but @stripe/stripe-js@").concat("9.9.0", " expected Stripe.js@").concat(expectedVersion, ". This may result in unexpected behavior. For more information, see https://docs.stripe.com/sdks/stripejs-versioning"));
23567
+ console.warn("Stripe.js@".concat(version, " was loaded on the page, but @stripe/stripe-js@").concat("9.12.0", " expected Stripe.js@").concat(expectedVersion, ". This may result in unexpected behavior. For more information, see https://docs.stripe.com/sdks/stripejs-versioning"));
23336
23568
  }
23337
23569
  var stripe = maybeStripe.apply(void 0, args);
23338
23570
  registerWrapper(stripe, startTime);
@@ -23746,14 +23978,17 @@ var UsageDetails2 = ({
23746
23978
  layout
23747
23979
  }) => {
23748
23980
  const { t: t3 } = useTranslation();
23749
- const { settings } = useEmbed();
23981
+ const { settings, warningThresholdConfig } = useEmbed();
23982
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
23750
23983
  const {
23751
23984
  billingPrice,
23752
23985
  limit,
23753
23986
  cost = 0
23754
23987
  } = (0, import_react56.useMemo)(
23755
- () => getUsageDetails(entitlement, period, currency),
23756
- [entitlement, period, currency]
23988
+ () => getUsageDetails(entitlement, period, currency, {
23989
+ showWarningThresholdAsLimit
23990
+ }),
23991
+ [entitlement, period, currency, showWarningThresholdAsLimit]
23757
23992
  );
23758
23993
  const description = (0, import_react56.useMemo)(() => {
23759
23994
  const acc = [];
@@ -24515,7 +24750,8 @@ var AddOn2 = ({
24515
24750
  }) => {
24516
24751
  const { layout } = sharedProps;
24517
24752
  const { t: t3 } = useTranslation();
24518
- const { data, settings, setCheckoutState } = useEmbed();
24753
+ const { data, settings, setCheckoutState, warningThresholdConfig } = useEmbed();
24754
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
24519
24755
  const isLightBackground = useIsLightBackground();
24520
24756
  const { currentAddOns, canCheckout, isStandalone } = (0, import_react58.useMemo)(() => {
24521
24757
  const isStandalone2 = typeof data?.component === "undefined";
@@ -24544,12 +24780,16 @@ var AddOn2 = ({
24544
24780
  selectedPeriod,
24545
24781
  currency
24546
24782
  );
24783
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
24547
24784
  return {
24548
24785
  isUnlimited: false,
24549
24786
  featureName: entitlement.feature?.name,
24550
24787
  feature: entitlement.feature,
24551
24788
  priceBehavior: entitlement.priceBehavior,
24552
24789
  softLimit: entitlement.softLimit,
24790
+ // The limit shown next to the feature: the warning threshold when the
24791
+ // option is on and one is configured, else the overage soft limit.
24792
+ limit: typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage ? entitlement.softLimit : void 0,
24553
24793
  price: priceData?.price ?? 0,
24554
24794
  currency: priceData?.currency || addOnCurrency,
24555
24795
  packageSize: priceData?.packageSize ?? 1,
@@ -24719,7 +24959,7 @@ var AddOn2 = ({
24719
24959
  rounded: true
24720
24960
  }
24721
24961
  ),
24722
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Flex, { $flexDirection: "column", $justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Text, { children: meteredEntitlement.priceBehavior === EntitlementPriceBehavior.Overage && meteredEntitlement.softLimit ? `${meteredEntitlement.softLimit} ${getEntitlementFeatureName(meteredEntitlement, "units")}` : getEntitlementFeatureName(meteredEntitlement) }) })
24962
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Flex, { $flexDirection: "column", $justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Text, { children: typeof meteredEntitlement.limit === "number" ? `${meteredEntitlement.limit} ${getEntitlementFeatureName(meteredEntitlement, "units")}` : getEntitlementFeatureName(meteredEntitlement) }) })
24723
24963
  ] }),
24724
24964
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24725
24965
  Text,
@@ -24790,7 +25030,8 @@ var Entitlement2 = ({
24790
25030
  }) => {
24791
25031
  const { layout } = sharedProps;
24792
25032
  const { t: t3 } = useTranslation();
24793
- const { settings } = useEmbed();
25033
+ const { settings, warningThresholdConfig } = useEmbed();
25034
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
24794
25035
  const isLightBackground = useIsLightBackground();
24795
25036
  const entitlementBillingPrice = getEntitlementPrice(
24796
25037
  entitlement,
@@ -24805,7 +25046,8 @@ var Entitlement2 = ({
24805
25046
  tiersMode: entitlementTiersMode
24806
25047
  } = entitlementBillingPrice || {};
24807
25048
  const tiered = entitlement.priceBehavior === EntitlementPriceBehavior.PayInAdvance && isTieredPrice(entitlementBillingPrice);
24808
- const limit = entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
25049
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
25050
+ const limit = typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
24809
25051
  const metricPeriodName = getMetricPeriodName(entitlement);
24810
25052
  const creditBasedEntitlementLimit = getCreditBasedEntitlementLimit(
24811
25053
  entitlement,
@@ -25695,20 +25937,27 @@ function resolveDesignProps11(props) {
25695
25937
  var UpcomingBill = (0, import_react63.forwardRef)(({ className, ...rest }, ref) => {
25696
25938
  const props = resolveDesignProps11(rest);
25697
25939
  const { t: t3 } = useTranslation();
25698
- const { data, settings, debug, getUpcomingInvoice, getCustomerBalance } = useEmbed();
25940
+ const { data, settings, getUpcomingInvoice } = useEmbed();
25699
25941
  const isLightBackground = useIsLightBackground();
25700
25942
  const [isLoading, setIsLoading] = (0, import_react63.useState)(false);
25701
25943
  const [error, setError] = (0, import_react63.useState)();
25702
25944
  const [upcomingInvoice, setUpcomingInvoice] = (0, import_react63.useState)(data?.upcomingInvoice);
25703
- const [balances, setBalances] = (0, import_react63.useState)([]);
25704
25945
  const discounts = (0, import_react63.useMemo)(() => {
25705
- return (data?.subscription?.discounts || []).map((discount) => ({
25946
+ return (data?.subscription?.discounts || []).filter(
25947
+ (discount) => (
25948
+ // Only surface discounts that are currently active and actually
25949
+ // reduce the bill; the API computes `isActive` at read time, so an
25950
+ // expired coupon must not linger in the account summary.
25951
+ discount.isActive && (typeof discount.percentOff === "number" && discount.percentOff > 0 || typeof discount.amountOff === "number" && discount.amountOff > 0)
25952
+ )
25953
+ ).map((discount) => ({
25706
25954
  couponId: discount.couponId,
25707
25955
  customerFacingCode: discount.customerFacingCode || void 0,
25708
25956
  currency: discount.currency || void 0,
25709
25957
  amountOff: discount.amountOff ?? void 0,
25710
25958
  percentOff: discount.percentOff ?? void 0,
25711
- isActive: discount.isActive
25959
+ duration: discount.duration,
25960
+ durationInMonths: discount.durationInMonths ?? void 0
25712
25961
  }));
25713
25962
  }, [data?.subscription?.discounts]);
25714
25963
  const getInvoice = (0, import_react63.useCallback)(async () => {
@@ -25727,27 +25976,30 @@ var UpcomingBill = (0, import_react63.forwardRef)(({ className, ...rest }, ref)
25727
25976
  }
25728
25977
  }
25729
25978
  }, [data?.component?.id, data?.subscription, getUpcomingInvoice]);
25730
- const getBalances = (0, import_react63.useCallback)(async () => {
25731
- try {
25732
- const response = await getCustomerBalance();
25733
- if (response) {
25734
- setBalances(response.data.balances);
25735
- }
25736
- } catch (err) {
25737
- debug("Failed to fetch customer balance.", err);
25738
- }
25739
- }, [debug, getCustomerBalance]);
25740
25979
  (0, import_react63.useEffect)(() => {
25741
25980
  getInvoice();
25742
25981
  }, [getInvoice]);
25743
- (0, import_react63.useEffect)(() => {
25744
- getBalances();
25745
- }, [getBalances]);
25746
25982
  (0, import_react63.useEffect)(() => {
25747
25983
  if (data?.upcomingInvoice) {
25748
25984
  setUpcomingInvoice(data.upcomingInvoice);
25749
25985
  }
25750
25986
  }, [data?.upcomingInvoice]);
25987
+ const { currency, applied, remaining } = (0, import_react63.useMemo)(() => {
25988
+ const currency2 = upcomingInvoice?.currency;
25989
+ const startingBalance = upcomingInvoice?.startingBalance ?? 0;
25990
+ const endingBalance = upcomingInvoice?.endingBalance ?? 0;
25991
+ const credit = Math.max(0, -startingBalance);
25992
+ const subtotal = Math.max(0, upcomingInvoice?.subtotal ?? 0);
25993
+ const applied2 = endingBalance < 0 ? credit + endingBalance : Math.min(credit, subtotal);
25994
+ return { currency: currency2, applied: applied2, remaining: credit - applied2 };
25995
+ }, [
25996
+ upcomingInvoice?.currency,
25997
+ upcomingInvoice?.startingBalance,
25998
+ upcomingInvoice?.endingBalance,
25999
+ upcomingInvoice?.subtotal
26000
+ ]);
26001
+ const hasApplied = applied > 0;
26002
+ const hasBalance = remaining > 0 || applied > 0;
25751
26003
  if (!data?.subscription || data.subscription.cancelAt) {
25752
26004
  return null;
25753
26005
  }
@@ -25797,7 +26049,7 @@ var UpcomingBill = (0, import_react63.forwardRef)(({ className, ...rest }, ref)
25797
26049
  ]
25798
26050
  }
25799
26051
  ),
25800
- balances.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26052
+ hasApplied && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
25801
26053
  Flex,
25802
26054
  {
25803
26055
  as: TransitionBox,
@@ -25805,8 +26057,21 @@ var UpcomingBill = (0, import_react63.forwardRef)(({ className, ...rest }, ref)
25805
26057
  $alignItems: "start",
25806
26058
  $gap: "1rem",
25807
26059
  children: [
25808
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { $weight: 600, children: t3("Remaining balance") }),
25809
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Flex, { $flexDirection: "column", $gap: "0.5rem", children: balances.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: formatCurrency(item.balance, item.currency) }, idx)) })
26060
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { $weight: 600, children: t3("Applied balance towards next invoice") }),
26061
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: formatCurrency(-applied, currency) })
26062
+ ]
26063
+ }
26064
+ ),
26065
+ hasBalance && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26066
+ Flex,
26067
+ {
26068
+ as: TransitionBox,
26069
+ $justifyContent: "space-between",
26070
+ $alignItems: "start",
26071
+ $gap: "1rem",
26072
+ children: [
26073
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { $weight: 600, children: t3("Remaining balance after next invoice") }),
26074
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: formatCurrency(remaining, currency) })
25810
26075
  ]
25811
26076
  }
25812
26077
  ),
@@ -25824,54 +26089,50 @@ var UpcomingBill = (0, import_react63.forwardRef)(({ className, ...rest }, ref)
25824
26089
  $flexDirection: "column",
25825
26090
  $alignItems: "end",
25826
26091
  $gap: "0.5rem",
25827
- children: discounts.reduce(
25828
- (acc, discount) => {
25829
- if (typeof discount.percentOff === "number" || typeof discount.amountOff === "number") {
25830
- acc.push(
25831
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26092
+ children: discounts.map((discount) => {
26093
+ const label = typeof discount.percentOff === "number" && discount.percentOff > 0 ? t3("Percent off", {
26094
+ percent: discount.percentOff
26095
+ }) : t3("Amount off", {
26096
+ amount: formatCurrency(
26097
+ discount.amountOff,
26098
+ // active discounts always carry a positive amount or percent
26099
+ discount?.currency
26100
+ )
26101
+ });
26102
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26103
+ Flex,
26104
+ {
26105
+ $alignItems: "center",
26106
+ $gap: "0.5rem",
26107
+ children: [
26108
+ discount.customerFacingCode && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
25832
26109
  Flex,
25833
26110
  {
25834
26111
  $alignItems: "center",
25835
- $gap: "0.5rem",
25836
- children: [
25837
- discount.customerFacingCode && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
25838
- Flex,
25839
- {
25840
- $alignItems: "center",
25841
- $padding: "0.1875rem 0.375rem",
25842
- $borderWidth: "1px",
25843
- $borderStyle: "solid",
25844
- $borderColor: isLightBackground ? "hsla(0, 0%, 0%, 0.15)" : "hsla(0, 0%, 100%, 0.15)",
25845
- $borderRadius: "0.3125rem",
25846
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
25847
- Text,
25848
- {
25849
- $size: 0.75 * settings.theme.typography.text.fontSize,
25850
- style: { textTransform: "uppercase" },
25851
- children: discount.customerFacingCode
25852
- }
25853
- )
25854
- }
25855
- ),
25856
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Box, { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: typeof discount.percentOff === "number" ? t3("Percent off", {
25857
- percent: discount.percentOff
25858
- }) : t3("Amount off", {
25859
- amount: formatCurrency(
25860
- discount.amountOff,
25861
- // we already checked for `number` type
25862
- discount?.currency
25863
- )
25864
- }) }) })
25865
- ]
25866
- },
25867
- discount.couponId
25868
- )
25869
- );
25870
- }
25871
- return acc;
25872
- },
25873
- []
25874
- )
26112
+ $padding: "0.1875rem 0.375rem",
26113
+ $borderWidth: "1px",
26114
+ $borderStyle: "solid",
26115
+ $borderColor: isLightBackground ? "hsla(0, 0%, 0%, 0.15)" : "hsla(0, 0%, 100%, 0.15)",
26116
+ $borderRadius: "0.3125rem",
26117
+ children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
26118
+ Text,
26119
+ {
26120
+ $size: 0.75 * settings.theme.typography.text.fontSize,
26121
+ style: { textTransform: "uppercase" },
26122
+ children: discount.customerFacingCode
26123
+ }
26124
+ )
26125
+ }
26126
+ ),
26127
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Box, { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: discount.duration === "repeating" && discount.durationInMonths ? t3("Discount for months", {
26128
+ discount: label,
26129
+ count: discount.durationInMonths
26130
+ }) : label }) })
26131
+ ]
26132
+ },
26133
+ discount.couponId
26134
+ );
26135
+ })
25875
26136
  }
25876
26137
  )
25877
26138
  ]