@schematichq/schematic-components 2.19.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.
@@ -778,7 +778,7 @@ var require_styled_components_cjs = __commonJS({
778
778
  var u = "undefined" != typeof process && void 0 !== process.env && (process.env.REACT_APP_SC_ATTR || process.env.SC_ATTR) || "data-styled";
779
779
  var d = "active";
780
780
  var h = "data-styled-version";
781
- var p = "6.4.3";
781
+ var p = "6.4.4";
782
782
  var f = "/*!sc*/\n";
783
783
  var m = "undefined" != typeof window && "undefined" != typeof document;
784
784
  var y = void 0 === a.default.createContext;
@@ -4698,7 +4698,10 @@ var Translator = class _Translator extends EventEmitter {
4698
4698
  const useOptionsReplaceForData = options.replace && !isString(options.replace);
4699
4699
  let data = useOptionsReplaceForData ? options.replace : options;
4700
4700
  if (useOptionsReplaceForData && typeof options.count !== "undefined") {
4701
- data.count = options.count;
4701
+ data = {
4702
+ ...data,
4703
+ count: options.count
4704
+ };
4702
4705
  }
4703
4706
  if (this.options.interpolation.defaultVariables) {
4704
4707
  data = {
@@ -5009,10 +5012,10 @@ var Interpolator = class {
5009
5012
  const skipOnVariables = options?.interpolation?.skipOnVariables !== void 0 ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables;
5010
5013
  const todos = [{
5011
5014
  regex: this.regexpUnescape,
5012
- safeValue: (val) => regexSafe(val)
5015
+ safeValue: (val) => val
5013
5016
  }, {
5014
5017
  regex: this.regexp,
5015
- safeValue: (val) => this.escapeValue ? regexSafe(this.escape(val)) : regexSafe(val)
5018
+ safeValue: (val) => this.escapeValue ? this.escape(val) : val
5016
5019
  }];
5017
5020
  todos.forEach((todo) => {
5018
5021
  replaces = 0;
@@ -5036,9 +5039,9 @@ var Interpolator = class {
5036
5039
  value = makeString(value);
5037
5040
  }
5038
5041
  const safeValue = todo.safeValue(value);
5039
- str = str.replace(match[0], safeValue);
5042
+ str = str.replace(match[0], regexSafe(safeValue));
5040
5043
  if (skipOnVariables) {
5041
- todo.regex.lastIndex += value.length;
5044
+ todo.regex.lastIndex += safeValue.length;
5042
5045
  todo.regex.lastIndex -= match[0].length;
5043
5046
  } else {
5044
5047
  todo.regex.lastIndex = 0;
@@ -5088,7 +5091,7 @@ var Interpolator = class {
5088
5091
  clonedOptions = clonedOptions.replace && !isString(clonedOptions.replace) ? clonedOptions.replace : clonedOptions;
5089
5092
  clonedOptions.applyPostProcessor = false;
5090
5093
  delete clonedOptions.defaultValue;
5091
- const keyEndIndex = /{.*}/.test(match[1]) ? match[1].lastIndexOf("}") + 1 : match[1].indexOf(this.formatSeparator);
5094
+ const keyEndIndex = /{.*}/s.test(match[1]) ? match[1].lastIndexOf("}") + 1 : match[1].indexOf(this.formatSeparator);
5092
5095
  if (keyEndIndex !== -1) {
5093
5096
  formatters = match[1].slice(keyEndIndex).split(this.formatSeparator).map((elem) => elem.trim()).filter(Boolean);
5094
5097
  match[1] = match[1].slice(0, keyEndIndex);
@@ -6820,6 +6823,9 @@ var en_default = {
6820
6823
  "After the trial, subscribe": "After the trial, subscription starts and you will be billed.",
6821
6824
  Agreement: "Agreement",
6822
6825
  "Amount off": "{{amount}} off",
6826
+ "Applied balance towards next invoice": "Applied balance towards next invoice",
6827
+ "Discount for months_one": "{{discount}} for next month",
6828
+ "Discount for months_other": "{{discount}} for next {{count}} months",
6823
6829
  "Auto Top-up": "Auto top-up",
6824
6830
  "Auto top-up enabled": "Auto top-up enabled",
6825
6831
  "Auto top-up disabled": "Auto top-up disabled",
@@ -6915,7 +6921,7 @@ var en_default = {
6915
6921
  Proration: "Proration",
6916
6922
  Quantity: "Quantity",
6917
6923
  "Quantity to pay for in advance": "Quantity to pay for in advance",
6918
- "Remaining balance": "Remaining balance",
6924
+ "Remaining balance after next invoice": "Remaining balance after next invoice",
6919
6925
  Remove: "Remove",
6920
6926
  "Remove add-on": "Remove add-on",
6921
6927
  Resets: "Resets {{date}}",
@@ -6990,6 +6996,14 @@ var en_default = {
6990
6996
  "X units per use": "{{amount}} {{units}} per use",
6991
6997
  "X time left in trial": "{{amount}} {{units}} left in trial",
6992
6998
  "Yearly total": "Yearly total",
6999
+ "You will be billed": "You will be billed {{price}} {{usage}}for this subscription every {{period}} {{schedule}}unless you unsubscribe.",
7000
+ "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.",
7001
+ "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.",
7002
+ "plus usage based costs": "plus usage based costs",
7003
+ "on the day": "on the {{day}}",
7004
+ "of month": "of {{month}}",
7005
+ "for the next months_one": "for the next month",
7006
+ "for the next months_other": "for the next {{count}} months",
6993
7007
  "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}}.",
6994
7008
  "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",
6995
7009
  "$X per unit": "{{cost}} per {{unit}}",
@@ -8188,11 +8202,13 @@ function InvoiceResponseDataFromJSONTyped(json, ignoreDiscriminator) {
8188
8202
  currency: json["currency"],
8189
8203
  customerExternalId: json["customer_external_id"],
8190
8204
  dueDate: json["due_date"] == null ? void 0 : new Date(json["due_date"]),
8205
+ endingBalance: json["ending_balance"],
8191
8206
  environmentId: json["environment_id"],
8192
8207
  externalId: json["external_id"] == null ? void 0 : json["external_id"],
8193
8208
  id: json["id"],
8194
8209
  paymentMethodExternalId: json["payment_method_external_id"] == null ? void 0 : json["payment_method_external_id"],
8195
8210
  providerType: BillingProviderTypeFromJSON(json["provider_type"]),
8211
+ startingBalance: json["starting_balance"],
8196
8212
  status: json["status"] == null ? void 0 : InvoiceStatusFromJSON(json["status"]),
8197
8213
  subscriptionExternalId: json["subscription_external_id"] == null ? void 0 : json["subscription_external_id"],
8198
8214
  subtotal: json["subtotal"],
@@ -8668,6 +8684,20 @@ function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
8668
8684
  return json;
8669
8685
  }
8670
8686
 
8687
+ // src/api/checkoutexternal/models/WarningTier.ts
8688
+ function WarningTierFromJSON(json) {
8689
+ return WarningTierFromJSONTyped(json, false);
8690
+ }
8691
+ function WarningTierFromJSONTyped(json, ignoreDiscriminator) {
8692
+ if (json == null) {
8693
+ return json;
8694
+ }
8695
+ return {
8696
+ key: json["key"],
8697
+ value: json["value"]
8698
+ };
8699
+ }
8700
+
8671
8701
  // src/api/checkoutexternal/models/FeatureEntitlement.ts
8672
8702
  function FeatureEntitlementFromJSON(json) {
8673
8703
  return FeatureEntitlementFromJSONTyped(json, false);
@@ -8694,7 +8724,8 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
8694
8724
  monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
8695
8725
  softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
8696
8726
  usage: json["usage"] == null ? void 0 : json["usage"],
8697
- valueType: EntitlementValueTypeFromJSON(json["value_type"])
8727
+ valueType: EntitlementValueTypeFromJSON(json["value_type"]),
8728
+ warningTiers: json["warning_tiers"] == null ? void 0 : json["warning_tiers"].map(WarningTierFromJSON)
8698
8729
  };
8699
8730
  }
8700
8731
 
@@ -9041,6 +9072,7 @@ function CompanyOverrideNoteResponseDataFromJSONTyped(json, ignoreDiscriminator)
9041
9072
  var FeatureType = {
9042
9073
  Boolean: "boolean",
9043
9074
  Event: "event",
9075
+ License: "license",
9044
9076
  Trait: "trait"
9045
9077
  };
9046
9078
  function FeatureTypeFromJSON(json) {
@@ -9073,13 +9105,15 @@ function FeatureResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9073
9105
  featureType: FeatureTypeFromJSON(json["feature_type"]),
9074
9106
  icon: json["icon"],
9075
9107
  id: json["id"],
9108
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
9076
9109
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON(json["lifecycle_phase"]),
9077
9110
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
9078
9111
  name: json["name"],
9079
9112
  pluralName: json["plural_name"] == null ? void 0 : json["plural_name"],
9080
9113
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
9081
9114
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
9082
- updatedAt: new Date(json["updated_at"])
9115
+ updatedAt: new Date(json["updated_at"]),
9116
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
9083
9117
  };
9084
9118
  }
9085
9119
 
@@ -9431,6 +9465,7 @@ function FeatureInPlanResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9431
9465
  flags: json["flags"].map(FlagInPlanResponseDataFromJSON),
9432
9466
  icon: json["icon"],
9433
9467
  id: json["id"],
9468
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
9434
9469
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON(json["lifecycle_phase"]),
9435
9470
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
9436
9471
  name: json["name"],
@@ -9439,7 +9474,8 @@ function FeatureInPlanResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9439
9474
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
9440
9475
  trait: json["trait"] == null ? void 0 : EntityTraitDefinitionResponseDataFromJSON(json["trait"]),
9441
9476
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
9442
- updatedAt: new Date(json["updated_at"])
9477
+ updatedAt: new Date(json["updated_at"]),
9478
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
9443
9479
  };
9444
9480
  }
9445
9481
 
@@ -9516,6 +9552,20 @@ function PlanCreditGrantViewFromJSONTyped(json, ignoreDiscriminator) {
9516
9552
  };
9517
9553
  }
9518
9554
 
9555
+ // src/api/checkoutexternal/models/PlanCatalogMembershipResponseData.ts
9556
+ function PlanCatalogMembershipResponseDataFromJSON(json) {
9557
+ return PlanCatalogMembershipResponseDataFromJSONTyped(json, false);
9558
+ }
9559
+ function PlanCatalogMembershipResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9560
+ if (json == null) {
9561
+ return json;
9562
+ }
9563
+ return {
9564
+ id: json["id"],
9565
+ name: json["name"]
9566
+ };
9567
+ }
9568
+
9519
9569
  // src/api/checkoutexternal/models/PlanCurrencyPricesResponseData.ts
9520
9570
  function PlanCurrencyPricesResponseDataFromJSON(json) {
9521
9571
  return PlanCurrencyPricesResponseDataFromJSONTyped(json, false);
@@ -9672,6 +9722,9 @@ function CompanyPlanDetailResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9672
9722
  ),
9673
9723
  billingProduct: json["billing_product"] == null ? void 0 : BillingProductDetailResponseDataFromJSON(json["billing_product"]),
9674
9724
  billingStrategy: BillingStrategyFromJSON(json["billing_strategy"]),
9725
+ catalogs: json["catalogs"] == null ? void 0 : json["catalogs"].map(
9726
+ PlanCatalogMembershipResponseDataFromJSON
9727
+ ),
9675
9728
  chargeType: ChargeTypeFromJSON(json["charge_type"]),
9676
9729
  companyCanTrial: json["company_can_trial"],
9677
9730
  companyCount: json["company_count"],
@@ -9845,6 +9898,9 @@ function PlanDetailResponseDataFromJSONTyped(json, ignoreDiscriminator) {
9845
9898
  ),
9846
9899
  billingProduct: json["billing_product"] == null ? void 0 : BillingProductDetailResponseDataFromJSON(json["billing_product"]),
9847
9900
  billingStrategy: BillingStrategyFromJSON(json["billing_strategy"]),
9901
+ catalogs: json["catalogs"] == null ? void 0 : json["catalogs"].map(
9902
+ PlanCatalogMembershipResponseDataFromJSON
9903
+ ),
9848
9904
  chargeType: ChargeTypeFromJSON(json["charge_type"]),
9849
9905
  companyCount: json["company_count"],
9850
9906
  companyId: json["company_id"] == null ? void 0 : json["company_id"],
@@ -10014,6 +10070,7 @@ function ComponentResponseDataFromJSONTyped(json, ignoreDiscriminator) {
10014
10070
  }
10015
10071
  return {
10016
10072
  ast: json["ast"] == null ? void 0 : json["ast"],
10073
+ catalogId: json["catalog_id"] == null ? void 0 : json["catalog_id"],
10017
10074
  createdAt: new Date(json["created_at"]),
10018
10075
  id: json["id"],
10019
10076
  name: json["name"],
@@ -10250,6 +10307,29 @@ function PreviewSubscriptionUpcomingInvoiceLineItemsFromJSONTyped(json, ignoreDi
10250
10307
  };
10251
10308
  }
10252
10309
 
10310
+ // src/api/checkoutexternal/models/PreviewSubscriptionDiscountResponseData.ts
10311
+ function PreviewSubscriptionDiscountResponseDataFromJSON(json) {
10312
+ return PreviewSubscriptionDiscountResponseDataFromJSONTyped(json, false);
10313
+ }
10314
+ function PreviewSubscriptionDiscountResponseDataFromJSONTyped(json, ignoreDiscriminator) {
10315
+ if (json == null) {
10316
+ return json;
10317
+ }
10318
+ return {
10319
+ amountOff: json["amount_off"] == null ? void 0 : json["amount_off"],
10320
+ couponName: json["coupon_name"],
10321
+ currency: json["currency"] == null ? void 0 : json["currency"],
10322
+ customerFacingCode: json["customer_facing_code"] == null ? void 0 : json["customer_facing_code"],
10323
+ duration: json["duration"],
10324
+ durationInMonths: json["duration_in_months"] == null ? void 0 : json["duration_in_months"],
10325
+ endedAt: json["ended_at"] == null ? void 0 : new Date(json["ended_at"]),
10326
+ isActive: json["is_active"],
10327
+ percentOff: json["percent_off"] == null ? void 0 : json["percent_off"],
10328
+ promoCodeExternalId: json["promo_code_external_id"] == null ? void 0 : json["promo_code_external_id"],
10329
+ startedAt: new Date(json["started_at"])
10330
+ };
10331
+ }
10332
+
10253
10333
  // src/api/checkoutexternal/models/PreviewSubscriptionFinanceResponseData.ts
10254
10334
  function PreviewSubscriptionFinanceResponseDataFromJSON(json) {
10255
10335
  return PreviewSubscriptionFinanceResponseDataFromJSONTyped(json, false);
@@ -10260,9 +10340,13 @@ function PreviewSubscriptionFinanceResponseDataFromJSONTyped(json, ignoreDiscrim
10260
10340
  }
10261
10341
  return {
10262
10342
  amountOff: json["amount_off"],
10343
+ discounts: json["discounts"].map(
10344
+ PreviewSubscriptionDiscountResponseDataFromJSON
10345
+ ),
10263
10346
  dueNow: json["due_now"],
10264
10347
  newCharges: json["new_charges"],
10265
10348
  percentOff: json["percent_off"],
10349
+ periodEnd: new Date(json["period_end"]),
10266
10350
  periodStart: new Date(json["period_start"]),
10267
10351
  promoCodeApplied: json["promo_code_applied"],
10268
10352
  proration: json["proration"],
@@ -11876,13 +11960,15 @@ function FeatureResponseDataFromJSONTyped5(json, ignoreDiscriminator) {
11876
11960
  featureType: FeatureTypeFromJSON2(json["feature_type"]),
11877
11961
  icon: json["icon"],
11878
11962
  id: json["id"],
11963
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
11879
11964
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON2(json["lifecycle_phase"]),
11880
11965
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
11881
11966
  name: json["name"],
11882
11967
  pluralName: json["plural_name"] == null ? void 0 : json["plural_name"],
11883
11968
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
11884
11969
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
11885
- updatedAt: new Date(json["updated_at"])
11970
+ updatedAt: new Date(json["updated_at"]),
11971
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
11886
11972
  };
11887
11973
  }
11888
11974
 
@@ -11939,6 +12025,7 @@ function FeatureInPlanResponseDataFromJSONTyped6(json, ignoreDiscriminator) {
11939
12025
  flags: json["flags"].map(FlagInPlanResponseDataFromJSON2),
11940
12026
  icon: json["icon"],
11941
12027
  id: json["id"],
12028
+ licenseId: json["license_id"] == null ? void 0 : json["license_id"],
11942
12029
  lifecyclePhase: json["lifecycle_phase"] == null ? void 0 : FeatureLifecyclePhaseFromJSON2(json["lifecycle_phase"]),
11943
12030
  maintainerAccountMemberId: json["maintainer_account_member_id"] == null ? void 0 : json["maintainer_account_member_id"],
11944
12031
  name: json["name"],
@@ -11947,7 +12034,8 @@ function FeatureInPlanResponseDataFromJSONTyped6(json, ignoreDiscriminator) {
11947
12034
  singularName: json["singular_name"] == null ? void 0 : json["singular_name"],
11948
12035
  trait: json["trait"] == null ? void 0 : EntityTraitDefinitionResponseDataFromJSON2(json["trait"]),
11949
12036
  traitId: json["trait_id"] == null ? void 0 : json["trait_id"],
11950
- updatedAt: new Date(json["updated_at"])
12037
+ updatedAt: new Date(json["updated_at"]),
12038
+ usageLimitTraitId: json["usage_limit_trait_id"] == null ? void 0 : json["usage_limit_trait_id"]
11951
12039
  };
11952
12040
  }
11953
12041
 
@@ -12126,6 +12214,20 @@ function PlanCreditGrantViewFromJSONTyped3(json, ignoreDiscriminator) {
12126
12214
  };
12127
12215
  }
12128
12216
 
12217
+ // src/api/componentspublic/models/PlanCatalogMembershipResponseData.ts
12218
+ function PlanCatalogMembershipResponseDataFromJSON2(json) {
12219
+ return PlanCatalogMembershipResponseDataFromJSONTyped5(json, false);
12220
+ }
12221
+ function PlanCatalogMembershipResponseDataFromJSONTyped5(json, ignoreDiscriminator) {
12222
+ if (json == null) {
12223
+ return json;
12224
+ }
12225
+ return {
12226
+ id: json["id"],
12227
+ name: json["name"]
12228
+ };
12229
+ }
12230
+
12129
12231
  // src/api/componentspublic/models/PlanCurrencyPricesResponseData.ts
12130
12232
  function PlanCurrencyPricesResponseDataFromJSON2(json) {
12131
12233
  return PlanCurrencyPricesResponseDataFromJSONTyped5(json, false);
@@ -12193,6 +12295,9 @@ function PlanViewPublicResponseDataFromJSONTyped(json, ignoreDiscriminator) {
12193
12295
  ),
12194
12296
  billingProduct: json["billing_product"] == null ? void 0 : BillingProductDetailResponseDataFromJSON2(json["billing_product"]),
12195
12297
  billingStrategy: BillingStrategyFromJSON2(json["billing_strategy"]),
12298
+ catalogs: json["catalogs"] == null ? void 0 : json["catalogs"].map(
12299
+ PlanCatalogMembershipResponseDataFromJSON2
12300
+ ),
12196
12301
  chargeType: ChargeTypeFromJSON2(json["charge_type"]),
12197
12302
  companyCount: json["company_count"],
12198
12303
  companyId: json["company_id"] == null ? void 0 : json["company_id"],
@@ -12810,7 +12915,7 @@ function getMetricPeriodName(entitlement) {
12810
12915
  const name = period ? PeriodName[period] : void 0;
12811
12916
  return name;
12812
12917
  }
12813
- function getUsageDetails(entitlement, period, currency) {
12918
+ function getUsageDetails(entitlement, period, currency, options) {
12814
12919
  const billingPrice = currency ? getEntitlementPrice(entitlement, period ?? "month", currency) : period === "year" ? entitlement.yearlyUsageBasedPrice : period === "quarter" ? entitlement.quarterlyUsageBasedPrice : period === "month" ? entitlement.monthlyUsageBasedPrice : void 0;
12815
12920
  let limit;
12816
12921
  if ((!entitlement.priceBehavior || entitlement.priceBehavior === EntitlementPriceBehavior.PayInAdvance) && typeof entitlement.allocation === "number") {
@@ -12858,8 +12963,21 @@ function getUsageDetails(entitlement, period, currency) {
12858
12963
  start = end + 1;
12859
12964
  }
12860
12965
  }
12966
+ if (options?.showWarningThresholdAsLimit) {
12967
+ const warningThreshold = getEntitlementWarningThreshold(
12968
+ entitlement.planEntitlement?.warningTiers
12969
+ );
12970
+ if (typeof warningThreshold === "number") {
12971
+ limit = warningThreshold;
12972
+ }
12973
+ }
12861
12974
  return { billingPrice, limit, amount, cost, currentTier };
12862
12975
  }
12976
+ var WARNING_TIER_DEFAULT_KEY = "default";
12977
+ function getEntitlementWarningThreshold(warningTiers) {
12978
+ const tier = warningTiers?.find((t2) => t2?.key === WARNING_TIER_DEFAULT_KEY);
12979
+ return typeof tier?.value === "number" ? tier.value : void 0;
12980
+ }
12863
12981
  function getCreditBasedEntitlementLimit(entitlement, credits) {
12864
12982
  const matchedCredit = credits.find(
12865
12983
  (credit) => credit.id === entitlement.valueCredit?.id
@@ -13407,85 +13525,6 @@ function modifyDate(date, days) {
13407
13525
  return copy2;
13408
13526
  }
13409
13527
 
13410
- // src/utils/error.ts
13411
- function isError(value) {
13412
- return value instanceof Error;
13413
- }
13414
- var ERROR_UNKNOWN = new Error("An unknown error occurred.");
13415
-
13416
- // src/utils/event.ts
13417
- var createKeyboardExecutionHandler = (fn) => {
13418
- const handler = (event) => {
13419
- if (event.key === "Enter" || event.key === " ") {
13420
- event.preventDefault();
13421
- fn?.(event);
13422
- }
13423
- };
13424
- return handler;
13425
- };
13426
-
13427
- // src/utils/markdown.tsx
13428
- var import_react13 = require("react");
13429
- var import_jsx_runtime2 = require("react/jsx-runtime");
13430
- var TOKEN = /(\[[^\]]+\]\([^)\s]+\))|(\*\*[^*]+\*\*)|(\*[^*]+\*)/g;
13431
- var LINK = /^\[([^\]]+)\]\(([^)\s]+)\)$/;
13432
- var isSafeUrl = (url) => {
13433
- try {
13434
- const { protocol } = new URL(url);
13435
- return protocol === "http:" || protocol === "https:";
13436
- } catch {
13437
- return false;
13438
- }
13439
- };
13440
- var renderOptInMarkdown = (text) => {
13441
- if (!text) {
13442
- return null;
13443
- }
13444
- const nodes = [];
13445
- let lastIndex = 0;
13446
- let key = 0;
13447
- TOKEN.lastIndex = 0;
13448
- let match;
13449
- while ((match = TOKEN.exec(text)) !== null) {
13450
- if (match.index > lastIndex) {
13451
- nodes.push(
13452
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react13.Fragment, { children: text.slice(lastIndex, match.index) }, key++)
13453
- );
13454
- }
13455
- const [token, link, bold, italic] = match;
13456
- if (link) {
13457
- const parts = LINK.exec(link);
13458
- if (parts && isSafeUrl(parts[2])) {
13459
- nodes.push(
13460
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13461
- Text,
13462
- {
13463
- as: "a",
13464
- display: "link",
13465
- href: parts[2],
13466
- target: "_blank",
13467
- rel: "noopener noreferrer",
13468
- children: parts[1]
13469
- },
13470
- key++
13471
- )
13472
- );
13473
- } else {
13474
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react13.Fragment, { children: parts ? parts[1] : token }, key++));
13475
- }
13476
- } else if (bold) {
13477
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: bold.slice(2, -2) }, key++));
13478
- } else if (italic) {
13479
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("em", { children: italic.slice(1, -1) }, key++));
13480
- }
13481
- lastIndex = match.index + token.length;
13482
- }
13483
- if (lastIndex < text.length) {
13484
- nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react13.Fragment, { children: text.slice(lastIndex) }, key));
13485
- }
13486
- return nodes;
13487
- };
13488
-
13489
13528
  // src/utils/string.ts
13490
13529
  var ZERO_DECIMAL_CURRENCIES = /* @__PURE__ */ new Set([
13491
13530
  "BIF",
@@ -13634,6 +13673,168 @@ function getCurrencySymbol(currency) {
13634
13673
  }
13635
13674
  }
13636
13675
 
13676
+ // src/utils/discount.ts
13677
+ function getSubscriptionDiscount(discounts, subscriptionTotal, subscriptionCurrency) {
13678
+ const activeDiscounts = (discounts || []).filter(
13679
+ (discount2) => discount2.isActive && (typeof discount2.percentOff === "number" && discount2.percentOff > 0 || typeof discount2.amountOff === "number" && discount2.amountOff > 0)
13680
+ );
13681
+ if (activeDiscounts.length !== 1) {
13682
+ return void 0;
13683
+ }
13684
+ const discount = activeDiscounts[0];
13685
+ const isPercentOff = typeof discount.percentOff === "number" && discount.percentOff > 0;
13686
+ if (!isPercentOff && discount.currency && subscriptionCurrency && discount.currency.toLowerCase() !== subscriptionCurrency.toLowerCase()) {
13687
+ return void 0;
13688
+ }
13689
+ const discountedTotal = isPercentOff ? subscriptionTotal * (1 - discount.percentOff / 100) : Math.max(0, subscriptionTotal - (discount.amountOff ?? 0));
13690
+ if (discountedTotal >= subscriptionTotal) {
13691
+ return void 0;
13692
+ }
13693
+ return {
13694
+ duration: discount.duration,
13695
+ durationInMonths: discount.durationInMonths ?? void 0,
13696
+ discountedPrice: formatCurrency(
13697
+ discountedTotal,
13698
+ subscriptionCurrency ?? void 0
13699
+ )
13700
+ };
13701
+ }
13702
+ function getBillingPreviewText({
13703
+ subscriptionPrice,
13704
+ planPeriod,
13705
+ periodStart,
13706
+ hasUsageBasedCosts,
13707
+ discount
13708
+ }, t2) {
13709
+ if (!subscriptionPrice) {
13710
+ return null;
13711
+ }
13712
+ const usage = hasUsageBasedCosts ? `${t2("plus usage based costs")} ` : "";
13713
+ const scheduleParts = [];
13714
+ if (periodStart) {
13715
+ scheduleParts.push(
13716
+ t2("on the day", { day: formatOrdinal(periodStart.getDate()) })
13717
+ );
13718
+ }
13719
+ if (planPeriod === "year" && periodStart) {
13720
+ scheduleParts.push(t2("of month", { month: getMonthName(periodStart) }));
13721
+ }
13722
+ const schedule = scheduleParts.length > 0 ? `${scheduleParts.join(" ")} ` : "";
13723
+ if (!discount) {
13724
+ return t2("You will be billed", {
13725
+ price: subscriptionPrice,
13726
+ usage,
13727
+ period: planPeriod,
13728
+ schedule
13729
+ });
13730
+ }
13731
+ const { duration, durationInMonths, discountedPrice } = discount;
13732
+ if (duration === "forever") {
13733
+ return t2("You will be billed", {
13734
+ price: discountedPrice,
13735
+ usage,
13736
+ period: planPeriod,
13737
+ schedule
13738
+ });
13739
+ }
13740
+ if (duration === "repeating" && durationInMonths) {
13741
+ return t2("You will be billed with discount window", {
13742
+ price: discountedPrice,
13743
+ usage,
13744
+ period: planPeriod,
13745
+ schedule,
13746
+ window: t2("for the next months", { count: durationInMonths }),
13747
+ fullPrice: subscriptionPrice
13748
+ });
13749
+ }
13750
+ return t2("You will be billed next bill discount", {
13751
+ price: discountedPrice,
13752
+ usage,
13753
+ period: planPeriod,
13754
+ schedule,
13755
+ fullPrice: subscriptionPrice
13756
+ });
13757
+ }
13758
+
13759
+ // src/utils/error.ts
13760
+ function isError(value) {
13761
+ return value instanceof Error;
13762
+ }
13763
+ var ERROR_UNKNOWN = new Error("An unknown error occurred.");
13764
+
13765
+ // src/utils/event.ts
13766
+ var createKeyboardExecutionHandler = (fn) => {
13767
+ const handler = (event) => {
13768
+ if (event.key === "Enter" || event.key === " ") {
13769
+ event.preventDefault();
13770
+ fn?.(event);
13771
+ }
13772
+ };
13773
+ return handler;
13774
+ };
13775
+
13776
+ // src/utils/markdown.tsx
13777
+ var import_react13 = require("react");
13778
+ var import_jsx_runtime2 = require("react/jsx-runtime");
13779
+ var TOKEN = /(\[[^\]]+\]\([^)\s]+\))|(\*\*[^*]+\*\*)|(\*[^*]+\*)/g;
13780
+ var LINK = /^\[([^\]]+)\]\(([^)\s]+)\)$/;
13781
+ var isSafeUrl = (url) => {
13782
+ try {
13783
+ const { protocol } = new URL(url);
13784
+ return protocol === "http:" || protocol === "https:";
13785
+ } catch {
13786
+ return false;
13787
+ }
13788
+ };
13789
+ var renderOptInMarkdown = (text) => {
13790
+ if (!text) {
13791
+ return null;
13792
+ }
13793
+ const nodes = [];
13794
+ let lastIndex = 0;
13795
+ let key = 0;
13796
+ TOKEN.lastIndex = 0;
13797
+ let match;
13798
+ while ((match = TOKEN.exec(text)) !== null) {
13799
+ if (match.index > lastIndex) {
13800
+ nodes.push(
13801
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react13.Fragment, { children: text.slice(lastIndex, match.index) }, key++)
13802
+ );
13803
+ }
13804
+ const [token, link, bold, italic] = match;
13805
+ if (link) {
13806
+ const parts = LINK.exec(link);
13807
+ if (parts && isSafeUrl(parts[2])) {
13808
+ nodes.push(
13809
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
13810
+ Text,
13811
+ {
13812
+ as: "a",
13813
+ display: "link",
13814
+ href: parts[2],
13815
+ target: "_blank",
13816
+ rel: "noopener noreferrer",
13817
+ children: parts[1]
13818
+ },
13819
+ key++
13820
+ )
13821
+ );
13822
+ } else {
13823
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react13.Fragment, { children: parts ? parts[1] : token }, key++));
13824
+ }
13825
+ } else if (bold) {
13826
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: bold.slice(2, -2) }, key++));
13827
+ } else if (italic) {
13828
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("em", { children: italic.slice(1, -1) }, key++));
13829
+ }
13830
+ lastIndex = match.index + token.length;
13831
+ }
13832
+ if (lastIndex < text.length) {
13833
+ nodes.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react13.Fragment, { children: text.slice(lastIndex) }, key));
13834
+ }
13835
+ return nodes;
13836
+ };
13837
+
13637
13838
  // src/utils/style.ts
13638
13839
  var import_styled_components2 = __toESM(require_styled_components_cjs());
13639
13840
  function attr(key, value) {
@@ -13890,7 +14091,7 @@ var reducer = (state, action) => {
13890
14091
  // src/context/EmbedProvider.tsx
13891
14092
  var import_jsx_runtime3 = require("react/jsx-runtime");
13892
14093
  var getCustomHeaders = (sessionId) => ({
13893
- "X-Schematic-Components-Version": "2.19.0",
14094
+ "X-Schematic-Components-Version": "2.21.0",
13894
14095
  "X-Schematic-Session-ID": sessionId
13895
14096
  });
13896
14097
  var normalizeCurrencyFilter = (filter) => {
@@ -13914,6 +14115,7 @@ var EmbedProvider = ({
13914
14115
  apiKey,
13915
14116
  apiConfig,
13916
14117
  currencyFilter,
14118
+ warningThresholdConfig,
13917
14119
  checkoutPrefill,
13918
14120
  ...options
13919
14121
  }) => {
@@ -13929,6 +14131,7 @@ var EmbedProvider = ({
13929
14131
  const providedState = {
13930
14132
  settings: opts.settings || {},
13931
14133
  currencyFilter: normalizeCurrencyFilter(currencyFilter),
14134
+ warningThresholdConfig,
13932
14135
  checkoutPrefill: normalizeCheckoutPrefill(checkoutPrefill)
13933
14136
  };
13934
14137
  const resolvedState = (0, import_merge2.default)({}, initialState, providedState);
@@ -14357,6 +14560,7 @@ var EmbedProvider = ({
14357
14560
  layout: state.layout,
14358
14561
  checkoutState: state.checkoutState,
14359
14562
  currencyFilter: state.currencyFilter,
14563
+ warningThresholdConfig: state.warningThresholdConfig,
14360
14564
  checkoutPrefill: state.checkoutPrefill,
14361
14565
  hydratePublic: debouncedHydratePublic,
14362
14566
  hydrate: debouncedHydrate,
@@ -16310,7 +16514,8 @@ var Entitlement = ({
16310
16514
  currency: selectedCurrency
16311
16515
  }) => {
16312
16516
  const { t: t2 } = useTranslation();
16313
- const { data, settings } = useEmbed();
16517
+ const { data, settings, warningThresholdConfig } = useEmbed();
16518
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
16314
16519
  const isLightBackground = useIsLightBackground();
16315
16520
  const showCredits = data?.displaySettings?.showCredits ?? true;
16316
16521
  const showFeatureDescription = data?.displaySettings?.showFeatureDescription ?? false;
@@ -16334,7 +16539,8 @@ var Entitlement = ({
16334
16539
  return;
16335
16540
  }
16336
16541
  const hasNumericValue = entitlement.valueType === EntitlementValueType.Numeric || entitlement.valueType === EntitlementValueType.Unlimited || entitlement.valueType === EntitlementValueType.Trait;
16337
- const limit = entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
16542
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
16543
+ const limit = typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
16338
16544
  const creditBasedEntitlementLimit = getCreditBasedEntitlementLimit(
16339
16545
  entitlement,
16340
16546
  credits
@@ -16427,7 +16633,8 @@ var Entitlement = ({
16427
16633
  currency,
16428
16634
  packageSize,
16429
16635
  tiered,
16430
- selectedCurrency
16636
+ selectedCurrency,
16637
+ showWarningThresholdAsLimit
16431
16638
  ]);
16432
16639
  const usageText = (0, import_react31.useMemo)(() => {
16433
16640
  if (!entitlement.feature) {
@@ -17158,7 +17365,8 @@ var AddOns = ({
17158
17365
  currency
17159
17366
  }) => {
17160
17367
  const { t: t2 } = useTranslation();
17161
- const { settings } = useEmbed();
17368
+ const { settings, warningThresholdConfig } = useEmbed();
17369
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
17162
17370
  const isLightBackground = useIsLightBackground();
17163
17371
  const periodKey = period === "year" ? "yearlyPrice" : period === "quarter" ? "quarterlyPrice" : "monthlyPrice";
17164
17372
  const cardPadding = settings.theme.card.padding / TEXT_BASE_SIZE;
@@ -17190,10 +17398,14 @@ var AddOns = ({
17190
17398
  period,
17191
17399
  currency
17192
17400
  );
17401
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
17193
17402
  return {
17194
17403
  isUnlimited: false,
17195
17404
  priceBehavior: entitlement.priceBehavior,
17196
17405
  softLimit: entitlement.softLimit,
17406
+ // The limit shown next to the feature: the warning threshold when
17407
+ // the option is on and one is configured, else the overage soft limit.
17408
+ limit: typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage ? entitlement.softLimit : void 0,
17197
17409
  price: priceData?.price ?? 0,
17198
17410
  currency: priceData?.currency || addOnCurrency,
17199
17411
  featureName: entitlement.feature?.name,
@@ -17342,7 +17554,7 @@ var AddOns = ({
17342
17554
  {
17343
17555
  $flexDirection: "column",
17344
17556
  $justifyContent: "center",
17345
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Text, { children: meteredEntitlement.priceBehavior === EntitlementPriceBehavior.Overage && meteredEntitlement.softLimit ? `${meteredEntitlement.softLimit} ${getEntitlementFeatureName(meteredEntitlement, "units")}` : getEntitlementFeatureName(meteredEntitlement) })
17557
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Text, { children: typeof meteredEntitlement.limit === "number" ? `${meteredEntitlement.limit} ${getEntitlementFeatureName(meteredEntitlement, "units")}` : getEntitlementFeatureName(meteredEntitlement) })
17346
17558
  }
17347
17559
  )
17348
17560
  ] }),
@@ -20628,7 +20840,7 @@ var SubscriptionSidebar = (0, import_react43.forwardRef)(
20628
20840
  );
20629
20841
  return { payAsYouGoEntitlements, payInAdvanceEntitlements: payInAdvanceEntitlements2 };
20630
20842
  }, [usageBasedEntitlements]);
20631
- const subscriptionPrice = (0, import_react43.useMemo)(() => {
20843
+ const { subscriptionPrice, subscriptionTotal, subscriptionCurrency } = (0, import_react43.useMemo)(() => {
20632
20844
  let planPrice;
20633
20845
  let resolvedCurrency;
20634
20846
  if (selectedPlan) {
@@ -20664,7 +20876,11 @@ var SubscriptionSidebar = (0, import_react43.forwardRef)(
20664
20876
  0
20665
20877
  );
20666
20878
  total += addOnPayInAdvanceCost;
20667
- return formatCurrency(total, resolvedCurrency);
20879
+ return {
20880
+ subscriptionPrice: formatCurrency(total, resolvedCurrency),
20881
+ subscriptionTotal: total,
20882
+ subscriptionCurrency: resolvedCurrency
20883
+ };
20668
20884
  }, [
20669
20885
  selectedPlan,
20670
20886
  currentPlan,
@@ -20679,6 +20895,7 @@ var SubscriptionSidebar = (0, import_react43.forwardRef)(
20679
20895
  dueNow,
20680
20896
  newCharges,
20681
20897
  percentOff,
20898
+ periodEnd,
20682
20899
  periodStart,
20683
20900
  proration,
20684
20901
  taxAmount,
@@ -20689,12 +20906,14 @@ var SubscriptionSidebar = (0, import_react43.forwardRef)(
20689
20906
  dueNow: charges?.dueNow ?? 0,
20690
20907
  newCharges: charges?.newCharges ?? 0,
20691
20908
  percentOff: charges?.percentOff ?? 0,
20909
+ periodEnd: charges?.periodEnd,
20692
20910
  periodStart: charges?.periodStart,
20693
20911
  proration: charges?.proration ?? 0,
20694
20912
  taxAmount: charges?.taxAmount ?? 0,
20695
20913
  taxDescription: charges?.taxDisplayName
20696
20914
  };
20697
20915
  }, [charges]);
20916
+ const renewDate = periodEnd && !Number.isNaN(periodEnd.getTime()) ? periodEnd : periodStart;
20698
20917
  const updatedUsageBasedEntitlements = (0, import_react43.useMemo)(() => {
20699
20918
  const changedUsageBasedEntitlements = [];
20700
20919
  const allSelectedUsageBasedEntitlements = [
@@ -20788,6 +21007,14 @@ var SubscriptionSidebar = (0, import_react43.forwardRef)(
20788
21007
  () => promoCode && (amountOff > 0 || percentOff > 0),
20789
21008
  [promoCode, amountOff, percentOff]
20790
21009
  );
21010
+ const subscriptionDiscount = (0, import_react43.useMemo)(
21011
+ () => getSubscriptionDiscount(
21012
+ charges?.discounts,
21013
+ subscriptionTotal,
21014
+ subscriptionCurrency
21015
+ ),
21016
+ [charges?.discounts, subscriptionTotal, subscriptionCurrency]
21017
+ );
20791
21018
  const handleCheckout = (0, import_react43.useCallback)(async () => {
20792
21019
  const planId = selectedPlan?.id;
20793
21020
  const currencyPrice = selectedPlan ? getPlanPrice(
@@ -21034,6 +21261,16 @@ var SubscriptionSidebar = (0, import_react43.forwardRef)(
21034
21261
  if (isSelectedPlanTrialable && selectedPlan.trialDays) {
21035
21262
  trialEndsOn.setDate(trialEndsOn.getDate() + selectedPlan.trialDays);
21036
21263
  }
21264
+ const billingPreviewText = getBillingPreviewText(
21265
+ {
21266
+ subscriptionPrice,
21267
+ planPeriod,
21268
+ periodStart: renewDate,
21269
+ hasUsageBasedCosts: usageBasedEntitlements.length > 0,
21270
+ discount: subscriptionDiscount
21271
+ },
21272
+ t2
21273
+ );
21037
21274
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
21038
21275
  Flex,
21039
21276
  {
@@ -21582,9 +21819,7 @@ var SubscriptionSidebar = (0, import_react43.forwardRef)(
21582
21819
  }
21583
21820
  )
21584
21821
  }
21585
- ) : subscriptionPrice && // TODO: localize
21586
- `You will be billed ${subscriptionPrice} ${usageBasedEntitlements.length > 0 ? "plus usage based costs" : ""} for this subscription
21587
- every ${planPeriod} ${periodStart ? `on the ${formatOrdinal(periodStart.getDate())}` : ""} ${planPeriod === "year" && periodStart ? `of ${getMonthName(periodStart)}` : ""} unless you unsubscribe.` }) })
21822
+ ) : billingPreviewText }) })
21588
21823
  ]
21589
21824
  }
21590
21825
  )
@@ -22105,7 +22340,8 @@ var UsageDetails = ({ entitlement, layout }) => {
22105
22340
  metricResetAt
22106
22341
  } = entitlement;
22107
22342
  const { t: t2 } = useTranslation();
22108
- const { data } = useEmbed();
22343
+ const { data, warningThresholdConfig } = useEmbed();
22344
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
22109
22345
  const period = getSubscriptionPeriod(data?.company?.billingSubscription) ?? data?.company?.plan?.planPeriod ?? void 0;
22110
22346
  const showCredits = data?.displaySettings?.showCredits ?? true;
22111
22347
  const {
@@ -22121,7 +22357,9 @@ var UsageDetails = ({ entitlement, layout }) => {
22121
22357
  } = (0, import_react48.useMemo)(() => {
22122
22358
  const { billingPrice, amount, limit: limit2, cost: cost2, currentTier: currentTier2 } = getUsageDetails(
22123
22359
  entitlement,
22124
- period
22360
+ period,
22361
+ void 0,
22362
+ { showWarningThresholdAsLimit }
22125
22363
  );
22126
22364
  const {
22127
22365
  price: price2,
@@ -22142,7 +22380,7 @@ var UsageDetails = ({ entitlement, layout }) => {
22142
22380
  tiersMode: tiersMode2,
22143
22381
  tiered: priceBehavior === EntitlementPriceBehavior.PayInAdvance && isTieredPrice(billingPrice)
22144
22382
  };
22145
- }, [entitlement, period, priceBehavior]);
22383
+ }, [entitlement, period, priceBehavior, showWarningThresholdAsLimit]);
22146
22384
  const text = (0, import_react48.useMemo)(() => {
22147
22385
  if (!feature || feature.featureType !== FeatureType.Event && feature.featureType !== FeatureType.Trait) {
22148
22386
  return;
@@ -22192,9 +22430,10 @@ var UsageDetails = ({ entitlement, layout }) => {
22192
22430
  });
22193
22431
  }
22194
22432
  if (!priceBehavior && typeof allocation === "number") {
22433
+ const numericLimit = limit ?? allocation;
22195
22434
  return t2("X units", {
22196
- amount: formatNumber(allocation),
22197
- units: getFeatureName(feature, allocation)
22435
+ amount: formatNumber(numericLimit),
22436
+ units: getFeatureName(feature, numericLimit)
22198
22437
  });
22199
22438
  }
22200
22439
  if (!priceBehavior && allocationType === "unlimited") {
@@ -22280,7 +22519,7 @@ var UsageDetails = ({ entitlement, layout }) => {
22280
22519
  if (typeof usage === "number") {
22281
22520
  return typeof allocation === "number" ? t2("usage.limited", {
22282
22521
  amount: formatNumber(usage),
22283
- allocation: formatNumber(allocation)
22522
+ allocation: formatNumber(limit ?? allocation)
22284
22523
  }) : t2("usage.unlimited", {
22285
22524
  amount: formatNumber(usage)
22286
22525
  });
@@ -22294,6 +22533,7 @@ var UsageDetails = ({ entitlement, layout }) => {
22294
22533
  priceBehavior,
22295
22534
  packageSize,
22296
22535
  allocation,
22536
+ limit,
22297
22537
  usage,
22298
22538
  metricResetAt,
22299
22539
  cost,
@@ -22725,7 +22965,12 @@ var import_react51 = require("react");
22725
22965
  var import_jsx_runtime51 = require("react/jsx-runtime");
22726
22966
  var Meter = ({ entitlement }) => {
22727
22967
  const { allocation, priceBehavior, softLimit, usage } = entitlement;
22728
- const limit = softLimit ?? allocation;
22968
+ const { warningThresholdConfig } = useEmbed();
22969
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
22970
+ const warningThreshold = getEntitlementWarningThreshold(
22971
+ entitlement.planEntitlement?.warningTiers
22972
+ );
22973
+ const limit = showWarningThresholdAsLimit && typeof warningThreshold === "number" ? warningThreshold : softLimit ?? allocation;
22729
22974
  if (typeof usage !== "number" || typeof limit !== "number") {
22730
22975
  return null;
22731
22976
  }
@@ -22865,14 +23110,7 @@ var import_jsx_runtime53 = require("react/jsx-runtime");
22865
23110
  var Limit = ({ entitlement, usageDetails, fontStyle }) => {
22866
23111
  const { t: t2 } = useTranslation();
22867
23112
  const { data } = useEmbed();
22868
- const {
22869
- feature,
22870
- planEntitlement,
22871
- priceBehavior,
22872
- allocation,
22873
- usage,
22874
- metricResetAt
22875
- } = entitlement;
23113
+ const { feature, planEntitlement, priceBehavior, usage, metricResetAt } = entitlement;
22876
23114
  const { billingPrice, limit, cost, currentTier } = usageDetails;
22877
23115
  const acc = [];
22878
23116
  acc.push(
@@ -22894,8 +23132,8 @@ var Limit = ({ entitlement, usageDetails, fontStyle }) => {
22894
23132
  }) : priceBehavior === EntitlementPriceBehavior.CreditBurndown && typeof feature !== "undefined" && typeof limit === "number" ? t2("X units remaining", {
22895
23133
  amount: formatNumber(limit),
22896
23134
  units: getFeatureName(feature, limit)
22897
- }) : typeof allocation === "number" ? t2("Limit of", {
22898
- amount: formatNumber(allocation)
23135
+ }) : typeof limit === "number" ? t2("Limit of", {
23136
+ amount: formatNumber(limit)
22899
23137
  }) : t2("No limit")
22900
23138
  );
22901
23139
  if (metricResetAt) {
@@ -22950,7 +23188,8 @@ var MeteredFeatures = (0, import_react51.forwardRef)(({ className, ...rest }, re
22950
23188
  const elementsRef = (0, import_react51.useRef)([]);
22951
23189
  const shouldWrapChildren = useWrapChildren(elementsRef);
22952
23190
  const { t: t2 } = useTranslation();
22953
- const { data, settings, setCheckoutState } = useEmbed();
23191
+ const { data, settings, setCheckoutState, warningThresholdConfig } = useEmbed();
23192
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
22954
23193
  const isLightBackground = useIsLightBackground();
22955
23194
  const meteredFeatures = (0, import_react51.useMemo)(() => {
22956
23195
  const orderedFeatureUsage = props.visibleFeatures?.reduce(
@@ -23004,7 +23243,9 @@ var MeteredFeatures = (0, import_react51.forwardRef)(({ className, ...rest }, re
23004
23243
  return acc;
23005
23244
  }
23006
23245
  const { feature, priceBehavior, usage } = entitlement;
23007
- const usageDetails = getUsageDetails(entitlement, period);
23246
+ const usageDetails = getUsageDetails(entitlement, period, void 0, {
23247
+ showWarningThresholdAsLimit
23248
+ });
23008
23249
  const { limit } = usageDetails;
23009
23250
  acc.push(
23010
23251
  /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(Element, { as: Flex, $flexDirection: "column", $gap: "1.5rem", children: [
@@ -23622,7 +23863,7 @@ var registerWrapper = function registerWrapper2(stripe, startTime) {
23622
23863
  }
23623
23864
  stripe._registerWrapper({
23624
23865
  name: "stripe-js",
23625
- version: "9.9.0",
23866
+ version: "9.12.0",
23626
23867
  startTime
23627
23868
  });
23628
23869
  };
@@ -23700,7 +23941,7 @@ var initStripe = function initStripe2(maybeStripe, args, startTime) {
23700
23941
  var version = runtimeVersionToUrlVersion(maybeStripe.version);
23701
23942
  var expectedVersion = RELEASE_TRAIN;
23702
23943
  if (isTestKey && version !== expectedVersion) {
23703
- 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"));
23944
+ 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"));
23704
23945
  }
23705
23946
  var stripe = maybeStripe.apply(void 0, args);
23706
23947
  registerWrapper(stripe, startTime);
@@ -24114,14 +24355,17 @@ var UsageDetails2 = ({
24114
24355
  layout
24115
24356
  }) => {
24116
24357
  const { t: t2 } = useTranslation();
24117
- const { settings } = useEmbed();
24358
+ const { settings, warningThresholdConfig } = useEmbed();
24359
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
24118
24360
  const {
24119
24361
  billingPrice,
24120
24362
  limit,
24121
24363
  cost = 0
24122
24364
  } = (0, import_react55.useMemo)(
24123
- () => getUsageDetails(entitlement, period, currency),
24124
- [entitlement, period, currency]
24365
+ () => getUsageDetails(entitlement, period, currency, {
24366
+ showWarningThresholdAsLimit
24367
+ }),
24368
+ [entitlement, period, currency, showWarningThresholdAsLimit]
24125
24369
  );
24126
24370
  const description = (0, import_react55.useMemo)(() => {
24127
24371
  const acc = [];
@@ -24883,7 +25127,8 @@ var AddOn2 = ({
24883
25127
  }) => {
24884
25128
  const { layout } = sharedProps;
24885
25129
  const { t: t2 } = useTranslation();
24886
- const { data, settings, setCheckoutState } = useEmbed();
25130
+ const { data, settings, setCheckoutState, warningThresholdConfig } = useEmbed();
25131
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
24887
25132
  const isLightBackground = useIsLightBackground();
24888
25133
  const { currentAddOns, canCheckout, isStandalone } = (0, import_react57.useMemo)(() => {
24889
25134
  const isStandalone2 = typeof data?.component === "undefined";
@@ -24912,12 +25157,16 @@ var AddOn2 = ({
24912
25157
  selectedPeriod,
24913
25158
  currency
24914
25159
  );
25160
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
24915
25161
  return {
24916
25162
  isUnlimited: false,
24917
25163
  featureName: entitlement.feature?.name,
24918
25164
  feature: entitlement.feature,
24919
25165
  priceBehavior: entitlement.priceBehavior,
24920
25166
  softLimit: entitlement.softLimit,
25167
+ // The limit shown next to the feature: the warning threshold when the
25168
+ // option is on and one is configured, else the overage soft limit.
25169
+ limit: typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage ? entitlement.softLimit : void 0,
24921
25170
  price: priceData?.price ?? 0,
24922
25171
  currency: priceData?.currency || addOnCurrency,
24923
25172
  packageSize: priceData?.packageSize ?? 1,
@@ -25087,7 +25336,7 @@ var AddOn2 = ({
25087
25336
  rounded: true
25088
25337
  }
25089
25338
  ),
25090
- /* @__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) }) })
25339
+ /* @__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) }) })
25091
25340
  ] }),
25092
25341
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
25093
25342
  Text,
@@ -25158,7 +25407,8 @@ var Entitlement2 = ({
25158
25407
  }) => {
25159
25408
  const { layout } = sharedProps;
25160
25409
  const { t: t2 } = useTranslation();
25161
- const { settings } = useEmbed();
25410
+ const { settings, warningThresholdConfig } = useEmbed();
25411
+ const showWarningThresholdAsLimit = warningThresholdConfig?.showAsLimit ?? false;
25162
25412
  const isLightBackground = useIsLightBackground();
25163
25413
  const entitlementBillingPrice = getEntitlementPrice(
25164
25414
  entitlement,
@@ -25173,7 +25423,8 @@ var Entitlement2 = ({
25173
25423
  tiersMode: entitlementTiersMode
25174
25424
  } = entitlementBillingPrice || {};
25175
25425
  const tiered = entitlement.priceBehavior === EntitlementPriceBehavior.PayInAdvance && isTieredPrice(entitlementBillingPrice);
25176
- const limit = entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
25426
+ const warningThreshold = showWarningThresholdAsLimit ? getEntitlementWarningThreshold(entitlement.warningTiers) : void 0;
25427
+ const limit = typeof warningThreshold === "number" ? warningThreshold : entitlement.priceBehavior === EntitlementPriceBehavior.Overage && typeof entitlement.softLimit === "number" ? entitlement.softLimit : entitlement.valueNumeric ?? void 0;
25177
25428
  const metricPeriodName = getMetricPeriodName(entitlement);
25178
25429
  const creditBasedEntitlementLimit = getCreditBasedEntitlementLimit(
25179
25430
  entitlement,
@@ -26063,20 +26314,27 @@ function resolveDesignProps11(props) {
26063
26314
  var UpcomingBill = (0, import_react62.forwardRef)(({ className, ...rest }, ref) => {
26064
26315
  const props = resolveDesignProps11(rest);
26065
26316
  const { t: t2 } = useTranslation();
26066
- const { data, settings, debug, getUpcomingInvoice, getCustomerBalance } = useEmbed();
26317
+ const { data, settings, getUpcomingInvoice } = useEmbed();
26067
26318
  const isLightBackground = useIsLightBackground();
26068
26319
  const [isLoading, setIsLoading] = (0, import_react62.useState)(false);
26069
26320
  const [error, setError] = (0, import_react62.useState)();
26070
26321
  const [upcomingInvoice, setUpcomingInvoice] = (0, import_react62.useState)(data?.upcomingInvoice);
26071
- const [balances, setBalances] = (0, import_react62.useState)([]);
26072
26322
  const discounts = (0, import_react62.useMemo)(() => {
26073
- return (data?.subscription?.discounts || []).map((discount) => ({
26323
+ return (data?.subscription?.discounts || []).filter(
26324
+ (discount) => (
26325
+ // Only surface discounts that are currently active and actually
26326
+ // reduce the bill; the API computes `isActive` at read time, so an
26327
+ // expired coupon must not linger in the account summary.
26328
+ discount.isActive && (typeof discount.percentOff === "number" && discount.percentOff > 0 || typeof discount.amountOff === "number" && discount.amountOff > 0)
26329
+ )
26330
+ ).map((discount) => ({
26074
26331
  couponId: discount.couponId,
26075
26332
  customerFacingCode: discount.customerFacingCode || void 0,
26076
26333
  currency: discount.currency || void 0,
26077
26334
  amountOff: discount.amountOff ?? void 0,
26078
26335
  percentOff: discount.percentOff ?? void 0,
26079
- isActive: discount.isActive
26336
+ duration: discount.duration,
26337
+ durationInMonths: discount.durationInMonths ?? void 0
26080
26338
  }));
26081
26339
  }, [data?.subscription?.discounts]);
26082
26340
  const getInvoice = (0, import_react62.useCallback)(async () => {
@@ -26095,27 +26353,30 @@ var UpcomingBill = (0, import_react62.forwardRef)(({ className, ...rest }, ref)
26095
26353
  }
26096
26354
  }
26097
26355
  }, [data?.component?.id, data?.subscription, getUpcomingInvoice]);
26098
- const getBalances = (0, import_react62.useCallback)(async () => {
26099
- try {
26100
- const response = await getCustomerBalance();
26101
- if (response) {
26102
- setBalances(response.data.balances);
26103
- }
26104
- } catch (err) {
26105
- debug("Failed to fetch customer balance.", err);
26106
- }
26107
- }, [debug, getCustomerBalance]);
26108
26356
  (0, import_react62.useEffect)(() => {
26109
26357
  getInvoice();
26110
26358
  }, [getInvoice]);
26111
- (0, import_react62.useEffect)(() => {
26112
- getBalances();
26113
- }, [getBalances]);
26114
26359
  (0, import_react62.useEffect)(() => {
26115
26360
  if (data?.upcomingInvoice) {
26116
26361
  setUpcomingInvoice(data.upcomingInvoice);
26117
26362
  }
26118
26363
  }, [data?.upcomingInvoice]);
26364
+ const { currency, applied, remaining } = (0, import_react62.useMemo)(() => {
26365
+ const currency2 = upcomingInvoice?.currency;
26366
+ const startingBalance = upcomingInvoice?.startingBalance ?? 0;
26367
+ const endingBalance = upcomingInvoice?.endingBalance ?? 0;
26368
+ const credit = Math.max(0, -startingBalance);
26369
+ const subtotal = Math.max(0, upcomingInvoice?.subtotal ?? 0);
26370
+ const applied2 = endingBalance < 0 ? credit + endingBalance : Math.min(credit, subtotal);
26371
+ return { currency: currency2, applied: applied2, remaining: credit - applied2 };
26372
+ }, [
26373
+ upcomingInvoice?.currency,
26374
+ upcomingInvoice?.startingBalance,
26375
+ upcomingInvoice?.endingBalance,
26376
+ upcomingInvoice?.subtotal
26377
+ ]);
26378
+ const hasApplied = applied > 0;
26379
+ const hasBalance = remaining > 0 || applied > 0;
26119
26380
  if (!data?.subscription || data.subscription.cancelAt) {
26120
26381
  return null;
26121
26382
  }
@@ -26165,7 +26426,7 @@ var UpcomingBill = (0, import_react62.forwardRef)(({ className, ...rest }, ref)
26165
26426
  ]
26166
26427
  }
26167
26428
  ),
26168
- balances.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26429
+ hasApplied && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26169
26430
  Flex,
26170
26431
  {
26171
26432
  as: TransitionBox,
@@ -26173,8 +26434,21 @@ var UpcomingBill = (0, import_react62.forwardRef)(({ className, ...rest }, ref)
26173
26434
  $alignItems: "start",
26174
26435
  $gap: "1rem",
26175
26436
  children: [
26176
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { $weight: 600, children: t2("Remaining balance") }),
26177
- /* @__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)) })
26437
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { $weight: 600, children: t2("Applied balance towards next invoice") }),
26438
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: formatCurrency(-applied, currency) })
26439
+ ]
26440
+ }
26441
+ ),
26442
+ hasBalance && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26443
+ Flex,
26444
+ {
26445
+ as: TransitionBox,
26446
+ $justifyContent: "space-between",
26447
+ $alignItems: "start",
26448
+ $gap: "1rem",
26449
+ children: [
26450
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { $weight: 600, children: t2("Remaining balance after next invoice") }),
26451
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: formatCurrency(remaining, currency) })
26178
26452
  ]
26179
26453
  }
26180
26454
  ),
@@ -26192,54 +26466,50 @@ var UpcomingBill = (0, import_react62.forwardRef)(({ className, ...rest }, ref)
26192
26466
  $flexDirection: "column",
26193
26467
  $alignItems: "end",
26194
26468
  $gap: "0.5rem",
26195
- children: discounts.reduce(
26196
- (acc, discount) => {
26197
- if (typeof discount.percentOff === "number" || typeof discount.amountOff === "number") {
26198
- acc.push(
26199
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26469
+ children: discounts.map((discount) => {
26470
+ const label = typeof discount.percentOff === "number" && discount.percentOff > 0 ? t2("Percent off", {
26471
+ percent: discount.percentOff
26472
+ }) : t2("Amount off", {
26473
+ amount: formatCurrency(
26474
+ discount.amountOff,
26475
+ // active discounts always carry a positive amount or percent
26476
+ discount?.currency
26477
+ )
26478
+ });
26479
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
26480
+ Flex,
26481
+ {
26482
+ $alignItems: "center",
26483
+ $gap: "0.5rem",
26484
+ children: [
26485
+ discount.customerFacingCode && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
26200
26486
  Flex,
26201
26487
  {
26202
26488
  $alignItems: "center",
26203
- $gap: "0.5rem",
26204
- children: [
26205
- discount.customerFacingCode && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
26206
- Flex,
26207
- {
26208
- $alignItems: "center",
26209
- $padding: "0.1875rem 0.375rem",
26210
- $borderWidth: "1px",
26211
- $borderStyle: "solid",
26212
- $borderColor: isLightBackground ? "hsla(0, 0%, 0%, 0.15)" : "hsla(0, 0%, 100%, 0.15)",
26213
- $borderRadius: "0.3125rem",
26214
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
26215
- Text,
26216
- {
26217
- $size: 0.75 * settings.theme.typography.text.fontSize,
26218
- style: { textTransform: "uppercase" },
26219
- children: discount.customerFacingCode
26220
- }
26221
- )
26222
- }
26223
- ),
26224
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Box, { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: typeof discount.percentOff === "number" ? t2("Percent off", {
26225
- percent: discount.percentOff
26226
- }) : t2("Amount off", {
26227
- amount: formatCurrency(
26228
- discount.amountOff,
26229
- // we already checked for `number` type
26230
- discount?.currency
26231
- )
26232
- }) }) })
26233
- ]
26234
- },
26235
- discount.couponId
26236
- )
26237
- );
26238
- }
26239
- return acc;
26240
- },
26241
- []
26242
- )
26489
+ $padding: "0.1875rem 0.375rem",
26490
+ $borderWidth: "1px",
26491
+ $borderStyle: "solid",
26492
+ $borderColor: isLightBackground ? "hsla(0, 0%, 0%, 0.15)" : "hsla(0, 0%, 100%, 0.15)",
26493
+ $borderRadius: "0.3125rem",
26494
+ children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
26495
+ Text,
26496
+ {
26497
+ $size: 0.75 * settings.theme.typography.text.fontSize,
26498
+ style: { textTransform: "uppercase" },
26499
+ children: discount.customerFacingCode
26500
+ }
26501
+ )
26502
+ }
26503
+ ),
26504
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Box, { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(Text, { children: discount.duration === "repeating" && discount.durationInMonths ? t2("Discount for months", {
26505
+ discount: label,
26506
+ count: discount.durationInMonths
26507
+ }) : label }) })
26508
+ ]
26509
+ },
26510
+ discount.couponId
26511
+ );
26512
+ })
26243
26513
  }
26244
26514
  )
26245
26515
  ]