@schematichq/schematic-components 0.6.1 → 0.6.3

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.
@@ -2167,7 +2167,7 @@ var require_debounce = __commonJS({
2167
2167
  var FUNC_ERROR_TEXT = "Expected a function";
2168
2168
  var nativeMax = Math.max;
2169
2169
  var nativeMin = Math.min;
2170
- function debounce2(func, wait, options) {
2170
+ function debounce3(func, wait, options) {
2171
2171
  var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
2172
2172
  if (typeof func != "function") {
2173
2173
  throw new TypeError(FUNC_ERROR_TEXT);
@@ -2248,7 +2248,7 @@ var require_debounce = __commonJS({
2248
2248
  debounced.flush = flush;
2249
2249
  return debounced;
2250
2250
  }
2251
- module2.exports = debounce2;
2251
+ module2.exports = debounce3;
2252
2252
  }
2253
2253
  });
2254
2254
 
@@ -3945,6 +3945,7 @@ var TEXT_BASE_SIZE = 16;
3945
3945
  var VISIBLE_ENTITLEMENT_COUNT = 4;
3946
3946
  var MAX_VISIBLE_INVOICE_COUNT = 12;
3947
3947
  var DEBOUNCE_TIMEOUT = 250;
3948
+ var DEFAULT_CURRENCY = "USD";
3948
3949
 
3949
3950
  // src/hooks/useAvailablePlans.ts
3950
3951
  var import_react10 = require("react");
@@ -13105,7 +13106,7 @@ var EmbedProvider = ({
13105
13106
  (0, import_react11.useEffect)(() => {
13106
13107
  if (accessToken) {
13107
13108
  const { headers = {} } = apiConfig ?? {};
13108
- headers["X-Schematic-Components-Version"] = "0.6.1";
13109
+ headers["X-Schematic-Components-Version"] = "0.6.3";
13109
13110
  headers["X-Schematic-Session-ID"] = sessionIdRef.current;
13110
13111
  const config = new Configuration({
13111
13112
  ...apiConfig,
@@ -13173,9 +13174,12 @@ var import_pluralize = __toESM(require_pluralize());
13173
13174
  var getFeatureName = (feature, count = 0) => {
13174
13175
  const shouldBePlural = count === 0 || count > 1;
13175
13176
  const { name, singularName, pluralName } = feature;
13176
- if (pluralName && shouldBePlural) return pluralName;
13177
- if (singularName)
13177
+ if (pluralName && shouldBePlural) {
13178
+ return pluralName;
13179
+ }
13180
+ if (singularName) {
13178
13181
  return shouldBePlural ? (0, import_pluralize.default)(singularName, count) : singularName;
13182
+ }
13179
13183
  return (0, import_pluralize.default)(name, count);
13180
13184
  };
13181
13185
 
@@ -13296,15 +13300,14 @@ function shortenPeriod(period) {
13296
13300
  }
13297
13301
 
13298
13302
  // src/utils/string.ts
13299
- var DEFAULT_CURRENCY = "USD";
13300
13303
  function camelToHyphen(str) {
13301
13304
  return str.replace(/([a-z][A-Z])/g, (g2) => `${g2[0]}-${g2[1].toLowerCase()}`);
13302
13305
  }
13303
13306
  function formatNumber(num) {
13304
13307
  return new Intl.NumberFormat("en-US").format(num);
13305
13308
  }
13306
- function formatCurrency(amount, currency = DEFAULT_CURRENCY) {
13307
- const nonEmptyCurrency = currency ? currency.toUpperCase() : DEFAULT_CURRENCY;
13309
+ function formatCurrency(amount, currency) {
13310
+ const resolvedCurrency = (currency || DEFAULT_CURRENCY).toUpperCase();
13308
13311
  try {
13309
13312
  const dollars = amount / 100;
13310
13313
  const formatValue = (value, symbol) => {
@@ -13312,8 +13315,8 @@ function formatCurrency(amount, currency = DEFAULT_CURRENCY) {
13312
13315
  if (formatted.endsWith(".0")) {
13313
13316
  formatted = formatted.slice(0, -2);
13314
13317
  }
13315
- if (nonEmptyCurrency !== DEFAULT_CURRENCY) {
13316
- return `${nonEmptyCurrency}${formatted}${symbol}`;
13318
+ if (resolvedCurrency !== DEFAULT_CURRENCY) {
13319
+ return `${resolvedCurrency}${formatted}${symbol}`;
13317
13320
  }
13318
13321
  return `$${formatted}${symbol}`;
13319
13322
  };
@@ -13324,14 +13327,16 @@ function formatCurrency(amount, currency = DEFAULT_CURRENCY) {
13324
13327
  } else {
13325
13328
  return new Intl.NumberFormat("en-US", {
13326
13329
  style: "currency",
13327
- currency: nonEmptyCurrency
13330
+ currency: resolvedCurrency,
13331
+ minimumSignificantDigits: 1,
13332
+ maximumSignificantDigits: 4
13328
13333
  }).format(dollars);
13329
13334
  }
13330
13335
  } catch (error) {
13331
13336
  console.error("Error formatting currency", error);
13332
13337
  return new Intl.NumberFormat("en-US", {
13333
13338
  style: "currency",
13334
- currency: nonEmptyCurrency
13339
+ currency: resolvedCurrency
13335
13340
  }).format(amount / 100);
13336
13341
  }
13337
13342
  }
@@ -14583,7 +14588,6 @@ var StyledCard = dt.div(({ theme }) => {
14583
14588
  const borderRadius = `${theme.card.borderRadius / TEXT_BASE_SIZE}rem`;
14584
14589
  return lt`
14585
14590
  position: relative;
14586
- overflow: hidden;
14587
14591
 
14588
14592
  ${theme.sectionLayout === "merged" ? `&:not(:has(${FussyChild}))` : `${Element}:not(:is(${FussyChild}))`} {
14589
14593
  color: ${theme.typography.text.color};
@@ -14661,7 +14665,10 @@ var import_react22 = require("react");
14661
14665
  var Container2 = dt(Box)`
14662
14666
  all: initial;
14663
14667
  box-sizing: border-box;
14668
+ display: block;
14664
14669
  font-size: ${TEXT_BASE_SIZE}px;
14670
+ width: 100%;
14671
+ height: 100%;
14665
14672
 
14666
14673
  *,
14667
14674
  *::before,
@@ -14694,6 +14701,7 @@ var Root = (0, import_react22.forwardRef)(
14694
14701
  Root.displayName = "Root";
14695
14702
 
14696
14703
  // src/components/layout/viewport/Viewport.tsx
14704
+ var import_debounce2 = __toESM(require_debounce());
14697
14705
  var import_react30 = require("react");
14698
14706
  var import_react_dom2 = require("react-dom");
14699
14707
 
@@ -16609,6 +16617,10 @@ var Plan = ({
16609
16617
  const count = entitlementCounts[plan.id];
16610
16618
  const isExpanded = count.limit > VISIBLE_ENTITLEMENT_COUNT;
16611
16619
  const { price: planPrice, currency: planCurrency } = (period === "month" ? plan.monthlyPrice : period === "year" && plan.yearlyPrice) || {};
16620
+ const hasUsageBasedEntitlements = plan.entitlements.some(
16621
+ (entitlement) => !!entitlement.priceBehavior
16622
+ );
16623
+ const isUsageBasedPlan = planPrice === 0 && hasUsageBasedEntitlements;
16612
16624
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
16613
16625
  Flex,
16614
16626
  {
@@ -16666,10 +16678,10 @@ var Plan = ({
16666
16678
  $size: theme.typography.heading2.fontSize,
16667
16679
  $weight: theme.typography.heading2.fontWeight,
16668
16680
  $color: theme.typography.heading2.color,
16669
- children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : formatCurrency(planPrice ?? 0, planCurrency)
16681
+ children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : isUsageBasedPlan ? t2("Usage-based") : formatCurrency(planPrice ?? 0, planCurrency)
16670
16682
  }
16671
16683
  ),
16672
- !plan.custom && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
16684
+ !plan.custom && !isUsageBasedPlan && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
16673
16685
  Text,
16674
16686
  {
16675
16687
  $font: theme.typography.heading2.fontFamily,
@@ -18209,16 +18221,19 @@ var Viewport = (0, import_react30.forwardRef)(
18209
18221
  const canCheckout = data.capabilities?.checkout ?? true;
18210
18222
  (0, import_react30.useLayoutEffect)(() => {
18211
18223
  const parent = portal || document.body;
18212
- setTop(
18213
- Math.abs(
18224
+ const setModalY = (0, import_debounce2.default)(() => {
18225
+ const value = Math.abs(
18214
18226
  (parent === document.body ? window.scrollY : parent.scrollTop) ?? 0
18215
- )
18216
- );
18227
+ );
18228
+ setTop(value);
18229
+ }, 250);
18217
18230
  parent.style.overflow = layout === "checkout" || layout === "unsubscribe" || layout === "payment" ? "hidden" : "";
18231
+ window.addEventListener("scroll", setModalY);
18218
18232
  return () => {
18233
+ window.removeEventListener("scroll", setModalY);
18219
18234
  parent.style.overflow = "";
18220
18235
  };
18221
- }, [layout, portal]);
18236
+ }, [portal, layout]);
18222
18237
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
18223
18238
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(StyledViewport, { ref, ...props, children: [
18224
18239
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RenderLayout, { children }),
@@ -18239,11 +18254,10 @@ Viewport.displayName = "Viewport";
18239
18254
  var import_react31 = require("react");
18240
18255
  var import_jsx_runtime27 = require("react/jsx-runtime");
18241
18256
  var Details = ({
18242
- details,
18243
18257
  shouldWrapChildren,
18258
+ featureUsage,
18244
18259
  ...props
18245
18260
  }) => {
18246
- const { featureUsage, usageData } = details;
18247
18261
  const {
18248
18262
  allocation,
18249
18263
  feature,
@@ -18252,7 +18266,7 @@ var Details = ({
18252
18266
  softLimit,
18253
18267
  monthlyUsageBasedPrice,
18254
18268
  yearlyUsageBasedPrice
18255
- } = featureUsage || {};
18269
+ } = featureUsage;
18256
18270
  const { t: t2 } = useTranslation();
18257
18271
  const theme = nt();
18258
18272
  const { data } = useEmbed();
@@ -18304,25 +18318,23 @@ var Details = ({
18304
18318
  if (!feature) {
18305
18319
  return;
18306
18320
  }
18307
- if (usageData) {
18308
- let acc;
18309
- if (priceBehavior === "pay_in_advance" && typeof data.company?.plan?.planPeriod === "string" && typeof price === "number") {
18310
- acc = `${formatCurrency(price, currency)}/${getFeatureName(feature, 1)}/${shortenPeriod(data.company.plan.planPeriod)}`;
18311
- } else if ((priceBehavior === "pay_as_you_go" || priceBehavior === "overage") && typeof usage === "number") {
18312
- acc = `${usage} ${getFeatureName(feature, usage)} ${t2("used")}`;
18313
- }
18314
- if (acc) {
18315
- if (priceBehavior === "pay_in_advance" && typeof price === "number" && typeof allocation === "number") {
18316
- acc += ` \u2022 ${formatCurrency(price * allocation, currency)}`;
18317
- } else if (priceBehavior === "pay_as_you_go" && typeof price === "number" && typeof usage === "number") {
18318
- acc += ` \u2022 ${formatCurrency(price * usage, currency)}`;
18319
- } else if (priceBehavior === "overage" && typeof price === "number" && typeof usage === "number" && typeof softLimit === "number") {
18320
- const cost = price * (usage - softLimit);
18321
- const period = feature.featureType === "event" && typeof data.company?.plan?.planPeriod === "string" ? `/${shortenPeriod(data.company.plan.planPeriod)}` : "";
18322
- acc += cost > 0 ? ` \u2022 ${t2("Overage")}: ${formatCurrency(cost)}${period}` : ` \u2022 ${`${formatCurrency(price)}/${getFeatureName(feature, 1)}`} ${t2("overage fee")}`;
18323
- }
18324
- return acc;
18321
+ let acc;
18322
+ if (priceBehavior === "pay_in_advance" && typeof data.company?.plan?.planPeriod === "string" && typeof price === "number") {
18323
+ acc = `${formatCurrency(price, currency)}/${getFeatureName(feature, 1)}/${shortenPeriod(data.company.plan.planPeriod)}`;
18324
+ } else if ((priceBehavior === "pay_as_you_go" || priceBehavior === "overage") && typeof usage === "number") {
18325
+ acc = `${usage} ${getFeatureName(feature, usage)} ${t2("used")}`;
18326
+ }
18327
+ if (acc) {
18328
+ if (priceBehavior === "pay_in_advance" && typeof price === "number" && typeof allocation === "number") {
18329
+ acc += ` \u2022 ${formatCurrency(price * allocation, currency)}`;
18330
+ } else if (priceBehavior === "pay_as_you_go" && typeof price === "number" && typeof usage === "number") {
18331
+ acc += ` \u2022 ${formatCurrency(price * usage, currency)}`;
18332
+ } else if (priceBehavior === "overage" && typeof price === "number" && typeof usage === "number" && typeof softLimit === "number") {
18333
+ const cost = price * (usage - softLimit);
18334
+ const period = feature.featureType === "event" && typeof data.company?.plan?.planPeriod === "string" ? `/${shortenPeriod(data.company.plan.planPeriod)}` : "";
18335
+ acc += cost > 0 ? ` \u2022 ${t2("Overage")}: ${formatCurrency(cost)}${period}` : ` \u2022 ${`${formatCurrency(price)}/${getFeatureName(feature, 1)}`} ${t2("overage fee")}`;
18325
18336
  }
18337
+ return acc;
18326
18338
  }
18327
18339
  if (typeof usage === "number") {
18328
18340
  return typeof allocation === "number" ? t2("usage.limited", {
@@ -18341,8 +18353,7 @@ var Details = ({
18341
18353
  price,
18342
18354
  currency,
18343
18355
  softLimit,
18344
- usage,
18345
- usageData
18356
+ usage
18346
18357
  ]);
18347
18358
  if (!text) {
18348
18359
  return null;
@@ -18420,38 +18431,28 @@ var IncludedFeatures = (0, import_react32.forwardRef)(({ className, ...rest }, r
18420
18431
  const shouldWrapChildren = useWrapChildren(elements.current);
18421
18432
  const isLightBackground = useIsLightBackground();
18422
18433
  const [showCount, setShowCount] = (0, import_react32.useState)(VISIBLE_ENTITLEMENT_COUNT);
18423
- const orderedFeatureUsage = props.visibleFeatures?.reduce(
18424
- (acc, id) => {
18425
- const mappedFeatureUsage = data.featureUsage?.features.find(
18426
- (usage) => usage.feature?.id === id
18427
- );
18428
- if (mappedFeatureUsage) {
18429
- acc.push(mappedFeatureUsage);
18430
- }
18431
- return acc;
18432
- },
18433
- []
18434
- );
18435
- const entitlements = (orderedFeatureUsage || data.featureUsage?.features || []).reduce(
18436
- (acc, usage) => {
18437
- const mappedUsageData = data.activeUsageBasedEntitlements.find(
18438
- (entitlement) => entitlement.featureId === usage.feature?.id
18439
- );
18440
- acc.push({
18441
- featureUsage: usage,
18442
- usageData: mappedUsageData
18443
- });
18444
- return acc;
18445
- },
18446
- []
18447
- );
18448
- const featureListSize = entitlements.length;
18434
+ const featureUsage = (0, import_react32.useMemo)(() => {
18435
+ const orderedFeatureUsage = props.visibleFeatures?.reduce(
18436
+ (acc, id) => {
18437
+ const mappedFeatureUsage = data.featureUsage?.features.find(
18438
+ (usage) => usage.feature?.id === id
18439
+ );
18440
+ if (mappedFeatureUsage) {
18441
+ acc.push(mappedFeatureUsage);
18442
+ }
18443
+ return acc;
18444
+ },
18445
+ []
18446
+ );
18447
+ return orderedFeatureUsage || data.featureUsage?.features || [];
18448
+ }, [props.visibleFeatures, data.featureUsage?.features]);
18449
+ const featureListSize = featureUsage.length;
18449
18450
  const handleToggleShowAll = () => {
18450
18451
  setShowCount(
18451
18452
  (prev2) => prev2 > VISIBLE_ENTITLEMENT_COUNT ? VISIBLE_ENTITLEMENT_COUNT : featureListSize
18452
18453
  );
18453
18454
  };
18454
- const shouldShowFeatures = entitlements.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18455
+ const shouldShowFeatures = featureUsage.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18455
18456
  if (!shouldShowFeatures) {
18456
18457
  return null;
18457
18458
  }
@@ -18476,8 +18477,8 @@ var IncludedFeatures = (0, import_react32.forwardRef)(({ className, ...rest }, r
18476
18477
  children: props.header.text
18477
18478
  }
18478
18479
  ) }),
18479
- entitlements.slice(0, showCount).map((entitlement, index) => {
18480
- const { entitlementExpirationDate, feature } = entitlement.featureUsage || {};
18480
+ featureUsage.slice(0, showCount).map((usage, index) => {
18481
+ const feature = usage.feature;
18481
18482
  const shouldShowDetails = feature?.name && (feature?.featureType === "event" || feature?.featureType === "trait");
18482
18483
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
18483
18484
  Flex,
@@ -18521,7 +18522,7 @@ var IncludedFeatures = (0, import_react32.forwardRef)(({ className, ...rest }, r
18521
18522
  children: feature.name
18522
18523
  }
18523
18524
  ),
18524
- props.entitlementExpiration.isVisible && entitlementExpirationDate && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
18525
+ props.entitlementExpiration.isVisible && usage.entitlementExpirationDate && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
18525
18526
  Text,
18526
18527
  {
18527
18528
  $font: theme.typography[props.entitlementExpiration.fontStyle].fontFamily,
@@ -18532,7 +18533,7 @@ var IncludedFeatures = (0, import_react32.forwardRef)(({ className, ...rest }, r
18532
18533
  children: [
18533
18534
  "Expires",
18534
18535
  " ",
18535
- toPrettyDate(entitlementExpirationDate, {
18536
+ toPrettyDate(usage.entitlementExpirationDate, {
18536
18537
  month: "short"
18537
18538
  })
18538
18539
  ]
@@ -18544,7 +18545,7 @@ var IncludedFeatures = (0, import_react32.forwardRef)(({ className, ...rest }, r
18544
18545
  shouldShowDetails && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
18545
18546
  Details,
18546
18547
  {
18547
- details: entitlement,
18548
+ featureUsage: usage,
18548
18549
  shouldWrapChildren,
18549
18550
  ...props
18550
18551
  }
@@ -18724,6 +18725,18 @@ var import_react34 = require("react");
18724
18725
  var Container4 = dt(Flex)`
18725
18726
  flex-direction: column;
18726
18727
 
18728
+ &:last-child {
18729
+ overflow: hidden;
18730
+
18731
+ ${({ theme }) => {
18732
+ const borderRadius = `${theme.card.borderRadius / TEXT_BASE_SIZE}rem`;
18733
+ return lt`
18734
+ border-bottom-left-radius: ${borderRadius};
18735
+ border-bottom-right-radius: ${borderRadius};
18736
+ `;
18737
+ }}
18738
+ }
18739
+
18727
18740
  &:not(:last-child) {
18728
18741
  ${({ theme }) => {
18729
18742
  const { l: l2 } = hexToHSL(theme.card.background);
@@ -18772,8 +18785,8 @@ var MeteredFeatures = (0, import_react34.forwardRef)(({ className, ...rest }, re
18772
18785
  const theme = nt();
18773
18786
  const { data, setLayout, setSelected } = useEmbed();
18774
18787
  const isLightBackground = useIsLightBackground();
18775
- const meteredFeatures = (0, import_react34.useMemo)(() => {
18776
- return (props.visibleFeatures ? props.visibleFeatures.reduce(
18788
+ const featureUsage = (0, import_react34.useMemo)(() => {
18789
+ const orderedFeatureUsage = props.visibleFeatures?.reduce(
18777
18790
  (acc, id) => {
18778
18791
  const mappedFeatureUsage = data.featureUsage?.features.find(
18779
18792
  (usage) => usage.feature?.id === id
@@ -18784,16 +18797,17 @@ var MeteredFeatures = (0, import_react34.forwardRef)(({ className, ...rest }, re
18784
18797
  return acc;
18785
18798
  },
18786
18799
  []
18787
- ) : data.featureUsage?.features || []).filter(
18800
+ );
18801
+ return (orderedFeatureUsage || data.featureUsage?.features || []).filter(
18788
18802
  (usage) => usage.feature?.featureType === "event" || usage.feature?.featureType === "trait"
18789
18803
  );
18790
18804
  }, [props.visibleFeatures, data.featureUsage?.features]);
18791
18805
  const planPeriod = data.company?.plan?.planPeriod;
18792
- const shouldShowFeatures = meteredFeatures.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18806
+ const shouldShowFeatures = featureUsage.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18793
18807
  if (!shouldShowFeatures) {
18794
18808
  return null;
18795
18809
  }
18796
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Container4, { ref, className, children: meteredFeatures.map(
18810
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Container4, { ref, className, children: featureUsage.map(
18797
18811
  ({
18798
18812
  feature,
18799
18813
  priceBehavior,
@@ -18807,7 +18821,7 @@ var MeteredFeatures = (0, import_react34.forwardRef)(({ className, ...rest }, re
18807
18821
  const limit = softLimit ?? allocation ?? 0;
18808
18822
  const isOverage = priceBehavior === "overage" && typeof softLimit === "number" && typeof usage === "number" && usage > softLimit;
18809
18823
  const { price, currency } = (planPeriod === "month" ? monthlyUsageBasedPrice : planPeriod === "year" && yearlyUsageBasedPrice) || {};
18810
- const progressBar = props.isVisible && typeof usage === "number" && priceBehavior !== "pay_as_you_go" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18824
+ const progressBar = props.isVisible && typeof usage === "number" && limit > 0 && priceBehavior !== "pay_as_you_go" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18811
18825
  ProgressBar,
18812
18826
  {
18813
18827
  progress: (isOverage ? softLimit / usage : usage / limit) * 100,
@@ -19685,6 +19699,7 @@ var PlanManager = (0, import_react38.forwardRef)(({ children, className, portal,
19685
19699
  const subscriptionCurrency = billingSubscription?.currency;
19686
19700
  const isTrialSubscription = billingSubscription?.status === "trialing";
19687
19701
  const willSubscriptionCancel = billingSubscription?.cancelAtPeriodEnd;
19702
+ const isUsageBasedPlan = currentPlan?.planPrice === 0 && usageBasedEntitlements.length > 0;
19688
19703
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
19689
19704
  isTrialSubscription && !willSubscriptionCancel ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
19690
19705
  Box,
@@ -19810,13 +19825,13 @@ var PlanManager = (0, import_react38.forwardRef)(({ children, className, portal,
19810
19825
  $size: theme.typography[props.header.price.fontStyle].fontSize,
19811
19826
  $weight: theme.typography[props.header.price.fontStyle].fontWeight,
19812
19827
  $color: theme.typography[props.header.price.fontStyle].color,
19813
- children: formatCurrency(
19828
+ children: isUsageBasedPlan ? t2("Usage-based") : formatCurrency(
19814
19829
  currentPlan.planPrice,
19815
19830
  subscriptionCurrency
19816
19831
  )
19817
19832
  }
19818
19833
  ),
19819
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19834
+ !isUsageBasedPlan && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
19820
19835
  Text,
19821
19836
  {
19822
19837
  $font: theme.typography[props.header.price.fontStyle].fontFamily,
@@ -20172,6 +20187,10 @@ var PricingTable = (0, import_react39.forwardRef)(({ children, className, ...res
20172
20187
  const { price: planPrice, currency: planCurrency } = (selectedPeriod === "month" ? plan.monthlyPrice : selectedPeriod === "year" && plan.yearlyPrice) || {};
20173
20188
  const count = entitlementCounts[plan.id];
20174
20189
  const isExpanded = count.limit > VISIBLE_ENTITLEMENT_COUNT;
20190
+ const hasUsageBasedEntitlements = plan.entitlements.some(
20191
+ (entitlement) => !!entitlement.priceBehavior
20192
+ );
20193
+ const isUsageBasedPlan = planPrice === 0 && hasUsageBasedEntitlements;
20175
20194
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
20176
20195
  Flex,
20177
20196
  {
@@ -20224,10 +20243,10 @@ var PricingTable = (0, import_react39.forwardRef)(({ children, className, ...res
20224
20243
  $size: theme.typography[props.plans.name.fontStyle].fontSize,
20225
20244
  $weight: theme.typography[props.plans.name.fontStyle].fontWeight,
20226
20245
  $color: theme.typography[props.plans.name.fontStyle].color,
20227
- children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : formatCurrency(planPrice ?? 0, planCurrency)
20246
+ children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : isUsageBasedPlan ? t2("Usage-based") : formatCurrency(planPrice ?? 0, planCurrency)
20228
20247
  }
20229
20248
  ),
20230
- !plan.custom && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
20249
+ !plan.custom && !isUsageBasedPlan && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
20231
20250
  Text,
20232
20251
  {
20233
20252
  $font: theme.typography[props.plans.name.fontStyle].fontFamily,
@@ -2167,7 +2167,7 @@ var require_debounce = __commonJS({
2167
2167
  var FUNC_ERROR_TEXT = "Expected a function";
2168
2168
  var nativeMax = Math.max;
2169
2169
  var nativeMin = Math.min;
2170
- function debounce2(func, wait, options) {
2170
+ function debounce3(func, wait, options) {
2171
2171
  var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
2172
2172
  if (typeof func != "function") {
2173
2173
  throw new TypeError(FUNC_ERROR_TEXT);
@@ -2248,12 +2248,12 @@ var require_debounce = __commonJS({
2248
2248
  debounced.flush = flush;
2249
2249
  return debounced;
2250
2250
  }
2251
- module.exports = debounce2;
2251
+ module.exports = debounce3;
2252
2252
  }
2253
2253
  });
2254
2254
 
2255
2255
  // src/components/elements/included-features/IncludedFeatures.tsx
2256
- import { forwardRef as forwardRef7, useRef as useRef7, useState as useState12 } from "react";
2256
+ import { forwardRef as forwardRef7, useMemo as useMemo9, useRef as useRef7, useState as useState12 } from "react";
2257
2257
 
2258
2258
  // node_modules/react-i18next/dist/es/Trans.js
2259
2259
  import { useContext } from "react";
@@ -3895,6 +3895,7 @@ var TEXT_BASE_SIZE = 16;
3895
3895
  var VISIBLE_ENTITLEMENT_COUNT = 4;
3896
3896
  var MAX_VISIBLE_INVOICE_COUNT = 12;
3897
3897
  var DEBOUNCE_TIMEOUT = 250;
3898
+ var DEFAULT_CURRENCY = "USD";
3898
3899
 
3899
3900
  // src/hooks/useAvailablePlans.ts
3900
3901
  import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
@@ -13055,7 +13056,7 @@ var EmbedProvider = ({
13055
13056
  useEffect2(() => {
13056
13057
  if (accessToken) {
13057
13058
  const { headers = {} } = apiConfig ?? {};
13058
- headers["X-Schematic-Components-Version"] = "0.6.1";
13059
+ headers["X-Schematic-Components-Version"] = "0.6.3";
13059
13060
  headers["X-Schematic-Session-ID"] = sessionIdRef.current;
13060
13061
  const config = new Configuration({
13061
13062
  ...apiConfig,
@@ -13123,9 +13124,12 @@ var import_pluralize = __toESM(require_pluralize());
13123
13124
  var getFeatureName = (feature, count = 0) => {
13124
13125
  const shouldBePlural = count === 0 || count > 1;
13125
13126
  const { name, singularName, pluralName } = feature;
13126
- if (pluralName && shouldBePlural) return pluralName;
13127
- if (singularName)
13127
+ if (pluralName && shouldBePlural) {
13128
+ return pluralName;
13129
+ }
13130
+ if (singularName) {
13128
13131
  return shouldBePlural ? (0, import_pluralize.default)(singularName, count) : singularName;
13132
+ }
13129
13133
  return (0, import_pluralize.default)(name, count);
13130
13134
  };
13131
13135
 
@@ -13246,15 +13250,14 @@ function shortenPeriod(period) {
13246
13250
  }
13247
13251
 
13248
13252
  // src/utils/string.ts
13249
- var DEFAULT_CURRENCY = "USD";
13250
13253
  function camelToHyphen(str) {
13251
13254
  return str.replace(/([a-z][A-Z])/g, (g2) => `${g2[0]}-${g2[1].toLowerCase()}`);
13252
13255
  }
13253
13256
  function formatNumber(num) {
13254
13257
  return new Intl.NumberFormat("en-US").format(num);
13255
13258
  }
13256
- function formatCurrency(amount, currency = DEFAULT_CURRENCY) {
13257
- const nonEmptyCurrency = currency ? currency.toUpperCase() : DEFAULT_CURRENCY;
13259
+ function formatCurrency(amount, currency) {
13260
+ const resolvedCurrency = (currency || DEFAULT_CURRENCY).toUpperCase();
13258
13261
  try {
13259
13262
  const dollars = amount / 100;
13260
13263
  const formatValue = (value, symbol) => {
@@ -13262,8 +13265,8 @@ function formatCurrency(amount, currency = DEFAULT_CURRENCY) {
13262
13265
  if (formatted.endsWith(".0")) {
13263
13266
  formatted = formatted.slice(0, -2);
13264
13267
  }
13265
- if (nonEmptyCurrency !== DEFAULT_CURRENCY) {
13266
- return `${nonEmptyCurrency}${formatted}${symbol}`;
13268
+ if (resolvedCurrency !== DEFAULT_CURRENCY) {
13269
+ return `${resolvedCurrency}${formatted}${symbol}`;
13267
13270
  }
13268
13271
  return `$${formatted}${symbol}`;
13269
13272
  };
@@ -13274,14 +13277,16 @@ function formatCurrency(amount, currency = DEFAULT_CURRENCY) {
13274
13277
  } else {
13275
13278
  return new Intl.NumberFormat("en-US", {
13276
13279
  style: "currency",
13277
- currency: nonEmptyCurrency
13280
+ currency: resolvedCurrency,
13281
+ minimumSignificantDigits: 1,
13282
+ maximumSignificantDigits: 4
13278
13283
  }).format(dollars);
13279
13284
  }
13280
13285
  } catch (error) {
13281
13286
  console.error("Error formatting currency", error);
13282
13287
  return new Intl.NumberFormat("en-US", {
13283
13288
  style: "currency",
13284
- currency: nonEmptyCurrency
13289
+ currency: resolvedCurrency
13285
13290
  }).format(amount / 100);
13286
13291
  }
13287
13292
  }
@@ -14533,7 +14538,6 @@ var StyledCard = dt.div(({ theme }) => {
14533
14538
  const borderRadius = `${theme.card.borderRadius / TEXT_BASE_SIZE}rem`;
14534
14539
  return lt`
14535
14540
  position: relative;
14536
- overflow: hidden;
14537
14541
 
14538
14542
  ${theme.sectionLayout === "merged" ? `&:not(:has(${FussyChild}))` : `${Element}:not(:is(${FussyChild}))`} {
14539
14543
  color: ${theme.typography.text.color};
@@ -14611,7 +14615,10 @@ import { forwardRef as forwardRef5 } from "react";
14611
14615
  var Container2 = dt(Box)`
14612
14616
  all: initial;
14613
14617
  box-sizing: border-box;
14618
+ display: block;
14614
14619
  font-size: ${TEXT_BASE_SIZE}px;
14620
+ width: 100%;
14621
+ height: 100%;
14615
14622
 
14616
14623
  *,
14617
14624
  *::before,
@@ -14644,6 +14651,7 @@ var Root = forwardRef5(
14644
14651
  Root.displayName = "Root";
14645
14652
 
14646
14653
  // src/components/layout/viewport/Viewport.tsx
14654
+ var import_debounce2 = __toESM(require_debounce());
14647
14655
  import { forwardRef as forwardRef6, useLayoutEffect as useLayoutEffect6, useState as useState11 } from "react";
14648
14656
  import { createPortal as createPortal2 } from "react-dom";
14649
14657
 
@@ -16569,6 +16577,10 @@ var Plan = ({
16569
16577
  const count = entitlementCounts[plan.id];
16570
16578
  const isExpanded = count.limit > VISIBLE_ENTITLEMENT_COUNT;
16571
16579
  const { price: planPrice, currency: planCurrency } = (period === "month" ? plan.monthlyPrice : period === "year" && plan.yearlyPrice) || {};
16580
+ const hasUsageBasedEntitlements = plan.entitlements.some(
16581
+ (entitlement) => !!entitlement.priceBehavior
16582
+ );
16583
+ const isUsageBasedPlan = planPrice === 0 && hasUsageBasedEntitlements;
16572
16584
  return /* @__PURE__ */ jsxs12(
16573
16585
  Flex,
16574
16586
  {
@@ -16626,10 +16638,10 @@ var Plan = ({
16626
16638
  $size: theme.typography.heading2.fontSize,
16627
16639
  $weight: theme.typography.heading2.fontWeight,
16628
16640
  $color: theme.typography.heading2.color,
16629
- children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : formatCurrency(planPrice ?? 0, planCurrency)
16641
+ children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : isUsageBasedPlan ? t2("Usage-based") : formatCurrency(planPrice ?? 0, planCurrency)
16630
16642
  }
16631
16643
  ),
16632
- !plan.custom && /* @__PURE__ */ jsxs12(
16644
+ !plan.custom && !isUsageBasedPlan && /* @__PURE__ */ jsxs12(
16633
16645
  Text,
16634
16646
  {
16635
16647
  $font: theme.typography.heading2.fontFamily,
@@ -18173,16 +18185,19 @@ var Viewport = forwardRef6(
18173
18185
  const canCheckout = data.capabilities?.checkout ?? true;
18174
18186
  useLayoutEffect6(() => {
18175
18187
  const parent = portal || document.body;
18176
- setTop(
18177
- Math.abs(
18188
+ const setModalY = (0, import_debounce2.default)(() => {
18189
+ const value = Math.abs(
18178
18190
  (parent === document.body ? window.scrollY : parent.scrollTop) ?? 0
18179
- )
18180
- );
18191
+ );
18192
+ setTop(value);
18193
+ }, 250);
18181
18194
  parent.style.overflow = layout === "checkout" || layout === "unsubscribe" || layout === "payment" ? "hidden" : "";
18195
+ window.addEventListener("scroll", setModalY);
18182
18196
  return () => {
18197
+ window.removeEventListener("scroll", setModalY);
18183
18198
  parent.style.overflow = "";
18184
18199
  };
18185
- }, [layout, portal]);
18200
+ }, [portal, layout]);
18186
18201
  return /* @__PURE__ */ jsxs20(Fragment9, { children: [
18187
18202
  /* @__PURE__ */ jsxs20(StyledViewport, { ref, ...props, children: [
18188
18203
  /* @__PURE__ */ jsx26(RenderLayout, { children }),
@@ -18203,11 +18218,10 @@ Viewport.displayName = "Viewport";
18203
18218
  import { useMemo as useMemo8 } from "react";
18204
18219
  import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
18205
18220
  var Details = ({
18206
- details,
18207
18221
  shouldWrapChildren,
18222
+ featureUsage,
18208
18223
  ...props
18209
18224
  }) => {
18210
- const { featureUsage, usageData } = details;
18211
18225
  const {
18212
18226
  allocation,
18213
18227
  feature,
@@ -18216,7 +18230,7 @@ var Details = ({
18216
18230
  softLimit,
18217
18231
  monthlyUsageBasedPrice,
18218
18232
  yearlyUsageBasedPrice
18219
- } = featureUsage || {};
18233
+ } = featureUsage;
18220
18234
  const { t: t2 } = useTranslation();
18221
18235
  const theme = nt();
18222
18236
  const { data } = useEmbed();
@@ -18268,25 +18282,23 @@ var Details = ({
18268
18282
  if (!feature) {
18269
18283
  return;
18270
18284
  }
18271
- if (usageData) {
18272
- let acc;
18273
- if (priceBehavior === "pay_in_advance" && typeof data.company?.plan?.planPeriod === "string" && typeof price === "number") {
18274
- acc = `${formatCurrency(price, currency)}/${getFeatureName(feature, 1)}/${shortenPeriod(data.company.plan.planPeriod)}`;
18275
- } else if ((priceBehavior === "pay_as_you_go" || priceBehavior === "overage") && typeof usage === "number") {
18276
- acc = `${usage} ${getFeatureName(feature, usage)} ${t2("used")}`;
18277
- }
18278
- if (acc) {
18279
- if (priceBehavior === "pay_in_advance" && typeof price === "number" && typeof allocation === "number") {
18280
- acc += ` \u2022 ${formatCurrency(price * allocation, currency)}`;
18281
- } else if (priceBehavior === "pay_as_you_go" && typeof price === "number" && typeof usage === "number") {
18282
- acc += ` \u2022 ${formatCurrency(price * usage, currency)}`;
18283
- } else if (priceBehavior === "overage" && typeof price === "number" && typeof usage === "number" && typeof softLimit === "number") {
18284
- const cost = price * (usage - softLimit);
18285
- const period = feature.featureType === "event" && typeof data.company?.plan?.planPeriod === "string" ? `/${shortenPeriod(data.company.plan.planPeriod)}` : "";
18286
- acc += cost > 0 ? ` \u2022 ${t2("Overage")}: ${formatCurrency(cost)}${period}` : ` \u2022 ${`${formatCurrency(price)}/${getFeatureName(feature, 1)}`} ${t2("overage fee")}`;
18287
- }
18288
- return acc;
18285
+ let acc;
18286
+ if (priceBehavior === "pay_in_advance" && typeof data.company?.plan?.planPeriod === "string" && typeof price === "number") {
18287
+ acc = `${formatCurrency(price, currency)}/${getFeatureName(feature, 1)}/${shortenPeriod(data.company.plan.planPeriod)}`;
18288
+ } else if ((priceBehavior === "pay_as_you_go" || priceBehavior === "overage") && typeof usage === "number") {
18289
+ acc = `${usage} ${getFeatureName(feature, usage)} ${t2("used")}`;
18290
+ }
18291
+ if (acc) {
18292
+ if (priceBehavior === "pay_in_advance" && typeof price === "number" && typeof allocation === "number") {
18293
+ acc += ` \u2022 ${formatCurrency(price * allocation, currency)}`;
18294
+ } else if (priceBehavior === "pay_as_you_go" && typeof price === "number" && typeof usage === "number") {
18295
+ acc += ` \u2022 ${formatCurrency(price * usage, currency)}`;
18296
+ } else if (priceBehavior === "overage" && typeof price === "number" && typeof usage === "number" && typeof softLimit === "number") {
18297
+ const cost = price * (usage - softLimit);
18298
+ const period = feature.featureType === "event" && typeof data.company?.plan?.planPeriod === "string" ? `/${shortenPeriod(data.company.plan.planPeriod)}` : "";
18299
+ acc += cost > 0 ? ` \u2022 ${t2("Overage")}: ${formatCurrency(cost)}${period}` : ` \u2022 ${`${formatCurrency(price)}/${getFeatureName(feature, 1)}`} ${t2("overage fee")}`;
18289
18300
  }
18301
+ return acc;
18290
18302
  }
18291
18303
  if (typeof usage === "number") {
18292
18304
  return typeof allocation === "number" ? t2("usage.limited", {
@@ -18305,8 +18317,7 @@ var Details = ({
18305
18317
  price,
18306
18318
  currency,
18307
18319
  softLimit,
18308
- usage,
18309
- usageData
18320
+ usage
18310
18321
  ]);
18311
18322
  if (!text) {
18312
18323
  return null;
@@ -18384,38 +18395,28 @@ var IncludedFeatures = forwardRef7(({ className, ...rest }, ref) => {
18384
18395
  const shouldWrapChildren = useWrapChildren(elements.current);
18385
18396
  const isLightBackground = useIsLightBackground();
18386
18397
  const [showCount, setShowCount] = useState12(VISIBLE_ENTITLEMENT_COUNT);
18387
- const orderedFeatureUsage = props.visibleFeatures?.reduce(
18388
- (acc, id) => {
18389
- const mappedFeatureUsage = data.featureUsage?.features.find(
18390
- (usage) => usage.feature?.id === id
18391
- );
18392
- if (mappedFeatureUsage) {
18393
- acc.push(mappedFeatureUsage);
18394
- }
18395
- return acc;
18396
- },
18397
- []
18398
- );
18399
- const entitlements = (orderedFeatureUsage || data.featureUsage?.features || []).reduce(
18400
- (acc, usage) => {
18401
- const mappedUsageData = data.activeUsageBasedEntitlements.find(
18402
- (entitlement) => entitlement.featureId === usage.feature?.id
18403
- );
18404
- acc.push({
18405
- featureUsage: usage,
18406
- usageData: mappedUsageData
18407
- });
18408
- return acc;
18409
- },
18410
- []
18411
- );
18412
- const featureListSize = entitlements.length;
18398
+ const featureUsage = useMemo9(() => {
18399
+ const orderedFeatureUsage = props.visibleFeatures?.reduce(
18400
+ (acc, id) => {
18401
+ const mappedFeatureUsage = data.featureUsage?.features.find(
18402
+ (usage) => usage.feature?.id === id
18403
+ );
18404
+ if (mappedFeatureUsage) {
18405
+ acc.push(mappedFeatureUsage);
18406
+ }
18407
+ return acc;
18408
+ },
18409
+ []
18410
+ );
18411
+ return orderedFeatureUsage || data.featureUsage?.features || [];
18412
+ }, [props.visibleFeatures, data.featureUsage?.features]);
18413
+ const featureListSize = featureUsage.length;
18413
18414
  const handleToggleShowAll = () => {
18414
18415
  setShowCount(
18415
18416
  (prev2) => prev2 > VISIBLE_ENTITLEMENT_COUNT ? VISIBLE_ENTITLEMENT_COUNT : featureListSize
18416
18417
  );
18417
18418
  };
18418
- const shouldShowFeatures = entitlements.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18419
+ const shouldShowFeatures = featureUsage.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18419
18420
  if (!shouldShowFeatures) {
18420
18421
  return null;
18421
18422
  }
@@ -18440,8 +18441,8 @@ var IncludedFeatures = forwardRef7(({ className, ...rest }, ref) => {
18440
18441
  children: props.header.text
18441
18442
  }
18442
18443
  ) }),
18443
- entitlements.slice(0, showCount).map((entitlement, index) => {
18444
- const { entitlementExpirationDate, feature } = entitlement.featureUsage || {};
18444
+ featureUsage.slice(0, showCount).map((usage, index) => {
18445
+ const feature = usage.feature;
18445
18446
  const shouldShowDetails = feature?.name && (feature?.featureType === "event" || feature?.featureType === "trait");
18446
18447
  return /* @__PURE__ */ jsxs22(
18447
18448
  Flex,
@@ -18485,7 +18486,7 @@ var IncludedFeatures = forwardRef7(({ className, ...rest }, ref) => {
18485
18486
  children: feature.name
18486
18487
  }
18487
18488
  ),
18488
- props.entitlementExpiration.isVisible && entitlementExpirationDate && /* @__PURE__ */ jsxs22(
18489
+ props.entitlementExpiration.isVisible && usage.entitlementExpirationDate && /* @__PURE__ */ jsxs22(
18489
18490
  Text,
18490
18491
  {
18491
18492
  $font: theme.typography[props.entitlementExpiration.fontStyle].fontFamily,
@@ -18496,7 +18497,7 @@ var IncludedFeatures = forwardRef7(({ className, ...rest }, ref) => {
18496
18497
  children: [
18497
18498
  "Expires",
18498
18499
  " ",
18499
- toPrettyDate(entitlementExpirationDate, {
18500
+ toPrettyDate(usage.entitlementExpirationDate, {
18500
18501
  month: "short"
18501
18502
  })
18502
18503
  ]
@@ -18508,7 +18509,7 @@ var IncludedFeatures = forwardRef7(({ className, ...rest }, ref) => {
18508
18509
  shouldShowDetails && /* @__PURE__ */ jsx28(
18509
18510
  Details,
18510
18511
  {
18511
- details: entitlement,
18512
+ featureUsage: usage,
18512
18513
  shouldWrapChildren,
18513
18514
  ...props
18514
18515
  }
@@ -18682,12 +18683,24 @@ var Invoices = forwardRef8(({ className, data, ...rest }, ref) => {
18682
18683
  Invoices.displayName = "Invoices";
18683
18684
 
18684
18685
  // src/components/elements/metered-features/MeteredFeatures.tsx
18685
- import { forwardRef as forwardRef9, useMemo as useMemo9, useRef as useRef8 } from "react";
18686
+ import { forwardRef as forwardRef9, useMemo as useMemo10, useRef as useRef8 } from "react";
18686
18687
 
18687
18688
  // src/components/elements/metered-features/styles.ts
18688
18689
  var Container4 = dt(Flex)`
18689
18690
  flex-direction: column;
18690
18691
 
18692
+ &:last-child {
18693
+ overflow: hidden;
18694
+
18695
+ ${({ theme }) => {
18696
+ const borderRadius = `${theme.card.borderRadius / TEXT_BASE_SIZE}rem`;
18697
+ return lt`
18698
+ border-bottom-left-radius: ${borderRadius};
18699
+ border-bottom-right-radius: ${borderRadius};
18700
+ `;
18701
+ }}
18702
+ }
18703
+
18691
18704
  &:not(:last-child) {
18692
18705
  ${({ theme }) => {
18693
18706
  const { l: l2 } = hexToHSL(theme.card.background);
@@ -18736,8 +18749,8 @@ var MeteredFeatures = forwardRef9(({ className, ...rest }, ref) => {
18736
18749
  const theme = nt();
18737
18750
  const { data, setLayout, setSelected } = useEmbed();
18738
18751
  const isLightBackground = useIsLightBackground();
18739
- const meteredFeatures = useMemo9(() => {
18740
- return (props.visibleFeatures ? props.visibleFeatures.reduce(
18752
+ const featureUsage = useMemo10(() => {
18753
+ const orderedFeatureUsage = props.visibleFeatures?.reduce(
18741
18754
  (acc, id) => {
18742
18755
  const mappedFeatureUsage = data.featureUsage?.features.find(
18743
18756
  (usage) => usage.feature?.id === id
@@ -18748,16 +18761,17 @@ var MeteredFeatures = forwardRef9(({ className, ...rest }, ref) => {
18748
18761
  return acc;
18749
18762
  },
18750
18763
  []
18751
- ) : data.featureUsage?.features || []).filter(
18764
+ );
18765
+ return (orderedFeatureUsage || data.featureUsage?.features || []).filter(
18752
18766
  (usage) => usage.feature?.featureType === "event" || usage.feature?.featureType === "trait"
18753
18767
  );
18754
18768
  }, [props.visibleFeatures, data.featureUsage?.features]);
18755
18769
  const planPeriod = data.company?.plan?.planPeriod;
18756
- const shouldShowFeatures = meteredFeatures.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18770
+ const shouldShowFeatures = featureUsage.length > 0 || data.company?.plan || (data.company?.addOns ?? []).length > 0 || false;
18757
18771
  if (!shouldShowFeatures) {
18758
18772
  return null;
18759
18773
  }
18760
- return /* @__PURE__ */ jsx30(Container4, { ref, className, children: meteredFeatures.map(
18774
+ return /* @__PURE__ */ jsx30(Container4, { ref, className, children: featureUsage.map(
18761
18775
  ({
18762
18776
  feature,
18763
18777
  priceBehavior,
@@ -18771,7 +18785,7 @@ var MeteredFeatures = forwardRef9(({ className, ...rest }, ref) => {
18771
18785
  const limit = softLimit ?? allocation ?? 0;
18772
18786
  const isOverage = priceBehavior === "overage" && typeof softLimit === "number" && typeof usage === "number" && usage > softLimit;
18773
18787
  const { price, currency } = (planPeriod === "month" ? monthlyUsageBasedPrice : planPeriod === "year" && yearlyUsageBasedPrice) || {};
18774
- const progressBar = props.isVisible && typeof usage === "number" && priceBehavior !== "pay_as_you_go" && /* @__PURE__ */ jsx30(
18788
+ const progressBar = props.isVisible && typeof usage === "number" && limit > 0 && priceBehavior !== "pay_as_you_go" && /* @__PURE__ */ jsx30(
18775
18789
  ProgressBar,
18776
18790
  {
18777
18791
  progress: (isOverage ? softLimit / usage : usage / limit) * 100,
@@ -18995,10 +19009,10 @@ var MeteredFeatures = forwardRef9(({ className, ...rest }, ref) => {
18995
19009
  MeteredFeatures.displayName = "MeteredFeatures";
18996
19010
 
18997
19011
  // src/components/elements/payment-method/PaymentMethod.tsx
18998
- import { forwardRef as forwardRef10, useMemo as useMemo11 } from "react";
19012
+ import { forwardRef as forwardRef10, useMemo as useMemo12 } from "react";
18999
19013
 
19000
19014
  // src/components/elements/payment-method/PaymentMethodElement.tsx
19001
- import { useMemo as useMemo10 } from "react";
19015
+ import { useMemo as useMemo11 } from "react";
19002
19016
  import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
19003
19017
  var PaymentElement2 = ({
19004
19018
  iconName,
@@ -19173,7 +19187,7 @@ var PaymentListElement = ({
19173
19187
  const isLightBackground = useIsLightBackground();
19174
19188
  const { iconName, iconTitle, label, paymentLast4 } = getPaymentMethodData(paymentMethod);
19175
19189
  const iconStyles = getIconStyles({ size: "lg", theme });
19176
- const expirationDate = useMemo10(() => {
19190
+ const expirationDate = useMemo11(() => {
19177
19191
  const { cardExpMonth, cardExpYear } = paymentMethod;
19178
19192
  if (!cardExpMonth && !cardExpYear) {
19179
19193
  return "";
@@ -19288,10 +19302,10 @@ var resolveDesignProps4 = (props) => {
19288
19302
  var PaymentMethod = forwardRef10(({ children, className, portal, allowEdit = true, ...rest }, ref) => {
19289
19303
  const props = resolveDesignProps4(rest);
19290
19304
  const { data, setLayout } = useEmbed();
19291
- const paymentMethod = useMemo11(() => {
19305
+ const paymentMethod = useMemo12(() => {
19292
19306
  return data.subscription?.paymentMethod;
19293
19307
  }, [data.subscription?.paymentMethod]);
19294
- const monthsToExpiration = useMemo11(() => {
19308
+ const monthsToExpiration = useMemo12(() => {
19295
19309
  let expiration;
19296
19310
  if (typeof paymentMethod?.cardExpYear === "number" && typeof paymentMethod?.cardExpMonth === "number") {
19297
19311
  const today = /* @__PURE__ */ new Date();
@@ -19318,7 +19332,7 @@ PaymentMethod.displayName = "PaymentMethod";
19318
19332
 
19319
19333
  // src/components/elements/payment-method/PaymentMethodDetails.tsx
19320
19334
  import { Elements } from "@stripe/react-stripe-js";
19321
- import { useCallback as useCallback10, useEffect as useEffect7, useMemo as useMemo12, useState as useState14 } from "react";
19335
+ import { useCallback as useCallback10, useEffect as useEffect7, useMemo as useMemo13, useState as useState14 } from "react";
19322
19336
  import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
19323
19337
  var resolveDesignProps5 = () => {
19324
19338
  return {
@@ -19352,7 +19366,7 @@ var PaymentMethodDetails = ({
19352
19366
  setPaymentMethod(data.subscription.paymentMethod);
19353
19367
  }
19354
19368
  }, [data.subscription?.paymentMethod]);
19355
- const monthsToExpiration = useMemo12(() => {
19369
+ const monthsToExpiration = useMemo13(() => {
19356
19370
  let expiration;
19357
19371
  if (typeof paymentMethod?.cardExpYear === "number" && typeof paymentMethod?.cardExpMonth === "number") {
19358
19372
  const today = /* @__PURE__ */ new Date();
@@ -19584,7 +19598,7 @@ var PaymentMethodDetails = ({
19584
19598
  };
19585
19599
 
19586
19600
  // src/components/elements/plan-manager/PlanManager.tsx
19587
- import { forwardRef as forwardRef11, useMemo as useMemo13 } from "react";
19601
+ import { forwardRef as forwardRef11, useMemo as useMemo14 } from "react";
19588
19602
  import { Fragment as Fragment11, jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
19589
19603
  var resolveDesignProps6 = (props) => {
19590
19604
  return {
@@ -19638,7 +19652,7 @@ var PlanManager = forwardRef11(({ children, className, portal, ...rest }, ref) =
19638
19652
  []
19639
19653
  );
19640
19654
  const billingSubscription = data.company?.billingSubscription;
19641
- const trialEndDays = useMemo13(() => {
19655
+ const trialEndDays = useMemo14(() => {
19642
19656
  const trialEnd = billingSubscription?.trialEnd;
19643
19657
  const trialEndDate = trialEnd ? new Date(trialEnd * 1e3) : /* @__PURE__ */ new Date();
19644
19658
  const todayDate = /* @__PURE__ */ new Date();
@@ -19649,6 +19663,7 @@ var PlanManager = forwardRef11(({ children, className, portal, ...rest }, ref) =
19649
19663
  const subscriptionCurrency = billingSubscription?.currency;
19650
19664
  const isTrialSubscription = billingSubscription?.status === "trialing";
19651
19665
  const willSubscriptionCancel = billingSubscription?.cancelAtPeriodEnd;
19666
+ const isUsageBasedPlan = currentPlan?.planPrice === 0 && usageBasedEntitlements.length > 0;
19652
19667
  return /* @__PURE__ */ jsxs27(Fragment11, { children: [
19653
19668
  isTrialSubscription && !willSubscriptionCancel ? /* @__PURE__ */ jsxs27(
19654
19669
  Box,
@@ -19774,13 +19789,13 @@ var PlanManager = forwardRef11(({ children, className, portal, ...rest }, ref) =
19774
19789
  $size: theme.typography[props.header.price.fontStyle].fontSize,
19775
19790
  $weight: theme.typography[props.header.price.fontStyle].fontWeight,
19776
19791
  $color: theme.typography[props.header.price.fontStyle].color,
19777
- children: formatCurrency(
19792
+ children: isUsageBasedPlan ? t2("Usage-based") : formatCurrency(
19778
19793
  currentPlan.planPrice,
19779
19794
  subscriptionCurrency
19780
19795
  )
19781
19796
  }
19782
19797
  ),
19783
- /* @__PURE__ */ jsx34(
19798
+ !isUsageBasedPlan && /* @__PURE__ */ jsx34(
19784
19799
  Text,
19785
19800
  {
19786
19801
  $font: theme.typography[props.header.price.fontStyle].fontFamily,
@@ -20136,6 +20151,10 @@ var PricingTable = forwardRef12(({ children, className, ...rest }, ref) => {
20136
20151
  const { price: planPrice, currency: planCurrency } = (selectedPeriod === "month" ? plan.monthlyPrice : selectedPeriod === "year" && plan.yearlyPrice) || {};
20137
20152
  const count = entitlementCounts[plan.id];
20138
20153
  const isExpanded = count.limit > VISIBLE_ENTITLEMENT_COUNT;
20154
+ const hasUsageBasedEntitlements = plan.entitlements.some(
20155
+ (entitlement) => !!entitlement.priceBehavior
20156
+ );
20157
+ const isUsageBasedPlan = planPrice === 0 && hasUsageBasedEntitlements;
20139
20158
  return /* @__PURE__ */ jsxs28(
20140
20159
  Flex,
20141
20160
  {
@@ -20188,10 +20207,10 @@ var PricingTable = forwardRef12(({ children, className, ...rest }, ref) => {
20188
20207
  $size: theme.typography[props.plans.name.fontStyle].fontSize,
20189
20208
  $weight: theme.typography[props.plans.name.fontStyle].fontWeight,
20190
20209
  $color: theme.typography[props.plans.name.fontStyle].color,
20191
- children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : formatCurrency(planPrice ?? 0, planCurrency)
20210
+ children: plan.custom ? plan.customPlanConfig?.priceText ? plan.customPlanConfig.priceText : t2("Custom Plan Price") : isUsageBasedPlan ? t2("Usage-based") : formatCurrency(planPrice ?? 0, planCurrency)
20192
20211
  }
20193
20212
  ),
20194
- !plan.custom && /* @__PURE__ */ jsxs28(
20213
+ !plan.custom && !isUsageBasedPlan && /* @__PURE__ */ jsxs28(
20195
20214
  Text,
20196
20215
  {
20197
20216
  $font: theme.typography[props.plans.name.fontStyle].fontFamily,
@@ -20778,7 +20797,7 @@ var UnsubscribeButton = forwardRef13(({ children, className, ...rest }, ref) =>
20778
20797
  UnsubscribeButton.displayName = "UnsubscribeButton";
20779
20798
 
20780
20799
  // src/components/elements/upcoming-bill/UpcomingBill.tsx
20781
- import { forwardRef as forwardRef14, useMemo as useMemo14 } from "react";
20800
+ import { forwardRef as forwardRef14, useMemo as useMemo15 } from "react";
20782
20801
  import { jsx as jsx37, jsxs as jsxs29 } from "react/jsx-runtime";
20783
20802
  function resolveDesignProps9(props) {
20784
20803
  return {
@@ -20804,7 +20823,7 @@ var UpcomingBill = forwardRef14(({ className, ...rest }, ref) => {
20804
20823
  const theme = nt();
20805
20824
  const { data } = useEmbed();
20806
20825
  const isLightBackground = useIsLightBackground();
20807
- const { upcomingInvoice, discounts } = useMemo14(() => {
20826
+ const { upcomingInvoice, discounts } = useMemo15(() => {
20808
20827
  const discounts2 = (data.subscription?.discounts || []).map((discount) => ({
20809
20828
  amountOff: discount.amountOff,
20810
20829
  couponId: discount.couponId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematichq/schematic-components",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "main": "dist/schematic-components.cjs.js",
5
5
  "module": "dist/schematic-components.esm.js",
6
6
  "types": "dist/schematic-components.d.ts",