@acarmisc/backstage-plugin-litellm 0.30.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -1060,16 +1060,21 @@ var init_Gauge = __esm({
1060
1060
  fontSize: size <= 64 ? 15 : 18,
1061
1061
  fontWeight: 700,
1062
1062
  fontVariantNumeric: "tabular-nums",
1063
- color: "text.primary"
1063
+ color: isOverCap ? "currentColor" : "text.primary"
1064
1064
  },
1065
- children: isOverCap ? "Over cap" : label ?? `${Math.round(value)}%`
1065
+ children: label ?? `${Math.round(value)}%`
1066
1066
  }
1067
1067
  ),
1068
1068
  caption && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1069
1069
  import_Typography3.default,
1070
1070
  {
1071
1071
  variant: "caption",
1072
- sx: { fontSize: 9.5, color: "text.secondary", mt: 0.25 },
1072
+ sx: {
1073
+ fontSize: 9.5,
1074
+ color: "text.secondary",
1075
+ mt: 0.25,
1076
+ whiteSpace: "nowrap"
1077
+ },
1073
1078
  children: caption
1074
1079
  }
1075
1080
  )
@@ -6577,6 +6582,7 @@ init_widgetState();
6577
6582
  // src/homeWidgetHelpers.ts
6578
6583
  init_format();
6579
6584
  init_tokens();
6585
+ init_dates();
6580
6586
  function rangeCaption(startDay, endDay) {
6581
6587
  return `${fmtDateShort(startDay)} \u2013 ${fmtDateShort(endDay)}`;
6582
6588
  }
@@ -6601,6 +6607,10 @@ function sparklineAriaLabel(points) {
6601
6607
  const peakDate = fmtDateShort(maxPoint.date);
6602
6608
  return `Daily spend over ${dayCount} day${dayCount === 1 ? "" : "s"}, total ${fmtUsd(total)}, peak ${fmtUsd(maxPoint.spend)} on ${peakDate}`;
6603
6609
  }
6610
+ function spendOnDay(points, now = /* @__PURE__ */ new Date()) {
6611
+ const day = toLocalDay(now);
6612
+ return points.find((p) => p.date === day)?.spend ?? 0;
6613
+ }
6604
6614
  function usageSummary(usage) {
6605
6615
  if (!usage) {
6606
6616
  return "$0.00 spent \xB7 0 in \xB7 0 out";
@@ -6829,7 +6839,76 @@ function resetLabel(limit) {
6829
6839
  const window2 = fmtBudgetDuration(limit.budgetDuration);
6830
6840
  return window2 ? `resets ${window2}` : "never resets";
6831
6841
  }
6832
- var LevelGauge = ({
6842
+ var Tag = ({ children, tone, title }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6843
+ import_Typography17.default,
6844
+ {
6845
+ title,
6846
+ sx: (theme) => ({
6847
+ fontSize: 10.5,
6848
+ fontWeight: 700,
6849
+ letterSpacing: "0.08em",
6850
+ textTransform: "uppercase",
6851
+ lineHeight: 1.3,
6852
+ color: tone ? toneColor(theme, tone) : theme.palette.text.secondary,
6853
+ whiteSpace: "nowrap",
6854
+ overflow: "hidden",
6855
+ textOverflow: "ellipsis"
6856
+ }),
6857
+ children
6858
+ }
6859
+ );
6860
+ var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0, flex: 1 }, children: [
6861
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "center", gap: 0.625, minWidth: 0 }, children: [
6862
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6863
+ import_Box19.default,
6864
+ {
6865
+ sx: (theme) => ({
6866
+ width: 6,
6867
+ height: 6,
6868
+ borderRadius: "50%",
6869
+ bgcolor: toneColor(theme, tone),
6870
+ flexShrink: 0
6871
+ })
6872
+ }
6873
+ ),
6874
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { children: label })
6875
+ ] }),
6876
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6877
+ import_Typography17.default,
6878
+ {
6879
+ title,
6880
+ sx: {
6881
+ fontSize: 19,
6882
+ fontWeight: 700,
6883
+ lineHeight: 1.15,
6884
+ mt: 0.25,
6885
+ fontVariantNumeric: "tabular-nums",
6886
+ whiteSpace: "nowrap",
6887
+ overflow: "hidden",
6888
+ textOverflow: "ellipsis"
6889
+ },
6890
+ children: value
6891
+ }
6892
+ ),
6893
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6894
+ import_Typography17.default,
6895
+ {
6896
+ variant: "caption",
6897
+ color: "text.secondary",
6898
+ sx: {
6899
+ display: "block",
6900
+ mt: 0.25,
6901
+ fontSize: 10.5,
6902
+ minHeight: 14,
6903
+ whiteSpace: "nowrap",
6904
+ overflow: "hidden",
6905
+ textOverflow: "ellipsis"
6906
+ },
6907
+ children: hint ?? ""
6908
+ }
6909
+ )
6910
+ ] });
6911
+ var LevelRow = ({
6833
6912
  gauge,
6834
6913
  size,
6835
6914
  keysHref
@@ -6838,14 +6917,42 @@ var LevelGauge = ({
6838
6917
  const limit = gauge.limit;
6839
6918
  const tone = limit ? budgetTone2(limit.pct) : "neutral";
6840
6919
  const extra = gauge.kind === "key" ? Math.max(0, gauge.count - 1) : 0;
6920
+ const overCap = Boolean(limit && limit.pct > 100);
6921
+ const subNote = () => {
6922
+ if (overCap) return "Over cap";
6923
+ if (extra > 0 && keysHref) {
6924
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6925
+ import_Typography17.default,
6926
+ {
6927
+ component: import_core_components5.Link,
6928
+ to: keysHref,
6929
+ variant: "caption",
6930
+ sx: {
6931
+ fontSize: 10.5,
6932
+ color: "primary.main",
6933
+ textDecoration: "none",
6934
+ "&:hover": { textDecoration: "underline" }
6935
+ },
6936
+ children: [
6937
+ "+",
6938
+ extra,
6939
+ " more"
6940
+ ]
6941
+ }
6942
+ );
6943
+ }
6944
+ return limit?.sublabel ?? null;
6945
+ };
6841
6946
  const gaugeAriaLabel = limit ? `${name} budget used: ${Math.round(limit.pct)}%` : `${name} \u2014 no cap`;
6842
6947
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6843
6948
  import_Box19.default,
6844
6949
  {
6845
6950
  sx: {
6846
- display: "flex",
6847
- flexDirection: "column",
6951
+ display: "grid",
6952
+ gridTemplateColumns: "auto minmax(0, 1fr) auto",
6848
6953
  alignItems: "center",
6954
+ gap: 1.25,
6955
+ py: 0.75,
6849
6956
  minWidth: 0
6850
6957
  },
6851
6958
  children: [
@@ -6859,84 +6966,109 @@ var LevelGauge = ({
6859
6966
  ariaLabel: gaugeAriaLabel
6860
6967
  }
6861
6968
  ),
6862
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6863
- import_Typography17.default,
6864
- {
6865
- sx: (theme) => ({
6866
- mt: 0.75,
6867
- fontSize: 10.5,
6868
- fontWeight: 700,
6869
- letterSpacing: "0.08em",
6870
- textTransform: "uppercase",
6871
- color: tone === "neutral" ? theme.palette.text.secondary : void 0
6872
- }),
6873
- children: name
6874
- }
6875
- ),
6876
- limit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6877
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6969
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0 }, children: [
6970
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { tone: tone === "warning" || tone === "danger" ? tone : void 0, children: name }),
6971
+ limit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6972
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6973
+ import_Typography17.default,
6974
+ {
6975
+ variant: "caption",
6976
+ title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label,
6977
+ sx: {
6978
+ display: "block",
6979
+ fontSize: 11.5,
6980
+ fontWeight: 600,
6981
+ lineHeight: 1.35,
6982
+ overflow: "hidden",
6983
+ textOverflow: "ellipsis",
6984
+ whiteSpace: "nowrap"
6985
+ },
6986
+ children: limit.label
6987
+ }
6988
+ ),
6989
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6990
+ import_Typography17.default,
6991
+ {
6992
+ variant: "caption",
6993
+ color: overCap ? "error" : "text.secondary",
6994
+ sx: {
6995
+ display: "block",
6996
+ fontSize: 10.5,
6997
+ fontWeight: overCap ? 700 : void 0,
6998
+ lineHeight: 1.35,
6999
+ overflow: "hidden",
7000
+ textOverflow: "ellipsis",
7001
+ whiteSpace: "nowrap"
7002
+ },
7003
+ children: subNote()
7004
+ }
7005
+ )
7006
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6878
7007
  import_Typography17.default,
6879
7008
  {
6880
7009
  variant: "caption",
6881
- title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label,
7010
+ color: "text.secondary",
6882
7011
  sx: {
6883
- mt: 0.25,
6884
- fontSize: 11,
6885
- fontWeight: 600,
6886
- maxWidth: "100%",
7012
+ display: "block",
7013
+ fontSize: 10.5,
7014
+ lineHeight: 1.35,
6887
7015
  overflow: "hidden",
6888
7016
  textOverflow: "ellipsis",
6889
7017
  whiteSpace: "nowrap"
6890
7018
  },
6891
- children: limit.label
7019
+ children: none
6892
7020
  }
6893
- ),
7021
+ )
7022
+ ] }),
7023
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0, textAlign: "right" }, children: [
6894
7024
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6895
7025
  import_Typography17.default,
6896
7026
  {
6897
- variant: "caption",
6898
- color: "text.secondary",
7027
+ title: limit ? `${fmtUsd(limit.spend)} of ${fmtUsd(limit.budget)}` : void 0,
6899
7028
  sx: {
6900
- fontSize: 10.5,
7029
+ display: "block",
7030
+ fontSize: 12.5,
7031
+ fontWeight: 600,
7032
+ lineHeight: 1.35,
6901
7033
  fontVariantNumeric: "tabular-nums",
6902
- textAlign: "center"
7034
+ whiteSpace: "nowrap",
7035
+ overflow: "hidden",
7036
+ textOverflow: "ellipsis",
7037
+ color: limit ? void 0 : "text.secondary"
6903
7038
  },
6904
- children: spendCaption(limit)
7039
+ children: amountCaption(limit)
6905
7040
  }
6906
7041
  ),
6907
- extra > 0 && keysHref ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7042
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6908
7043
  import_Typography17.default,
6909
7044
  {
6910
- component: import_core_components5.Link,
6911
- to: keysHref,
6912
7045
  variant: "caption",
7046
+ color: "text.secondary",
6913
7047
  sx: {
7048
+ display: "block",
6914
7049
  fontSize: 10.5,
6915
- color: "primary.main",
6916
- textDecoration: "none",
6917
- "&:hover": { textDecoration: "underline" }
7050
+ lineHeight: 1.35,
7051
+ whiteSpace: "nowrap",
7052
+ overflow: "hidden",
7053
+ textOverflow: "ellipsis"
6918
7054
  },
6919
- children: [
6920
- "+",
6921
- extra,
6922
- " more"
6923
- ]
7055
+ children: amountNote(limit)
6924
7056
  }
6925
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 10.5 }, children: resetLabel(limit) })
6926
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6927
- import_Typography17.default,
6928
- {
6929
- variant: "caption",
6930
- color: "text.secondary",
6931
- sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" },
6932
- children: none
6933
- }
6934
- )
7057
+ )
7058
+ ] })
6935
7059
  ]
6936
7060
  }
6937
7061
  );
6938
7062
  };
6939
- var UsageMiniChart = ({ data, totalSpend, loading, height, usageUnavailable = false, maxBudget }) => {
7063
+ function amountCaption(limit) {
7064
+ if (!limit) return "";
7065
+ return limit.hidden ? `${Math.round(limit.pct)}%` : spendCaption(limit);
7066
+ }
7067
+ function amountNote(limit) {
7068
+ if (!limit) return "";
7069
+ return limit.hidden ? "hidden by admin" : resetLabel(limit);
7070
+ }
7071
+ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, maxBudget }) => {
6940
7072
  const renderPlot = () => {
6941
7073
  if (loading) {
6942
7074
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "rectangular", width: "100%", height: "100%" });
@@ -6982,99 +7114,70 @@ var UsageMiniChart = ({ data, totalSpend, loading, height, usageUnavailable = fa
6982
7114
  )
6983
7115
  ] }) });
6984
7116
  };
6985
- const renderCaption = () => {
6986
- if (loading) {
6987
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "caption", color: "text.secondary", sx: { mt: 0.25, fontSize: 11 }, children: "\u2026" });
6988
- }
6989
- if (usageUnavailable) {
6990
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6991
- import_Typography17.default,
6992
- {
6993
- variant: "caption",
6994
- color: "text.secondary",
6995
- sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" },
6996
- children: USAGE_UNAVAILABLE_MSG
6997
- }
6998
- );
6999
- }
7000
- if (data.length === 0) {
7001
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7002
- import_Typography17.default,
7003
- {
7004
- variant: "caption",
7005
- color: "text.secondary",
7006
- sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" },
7007
- children: "No spend this month"
7008
- }
7009
- );
7010
- }
7011
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
7012
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7013
- import_Typography17.default,
7014
- {
7015
- variant: "caption",
7016
- title: `${fmtUsd(totalSpend)} spent month to date`,
7017
- sx: {
7018
- mt: 0.25,
7019
- fontSize: 11,
7020
- fontWeight: 600,
7021
- maxWidth: "100%",
7022
- overflow: "hidden",
7023
- textOverflow: "ellipsis",
7024
- whiteSpace: "nowrap",
7025
- fontVariantNumeric: "tabular-nums"
7026
- },
7027
- children: fmtUsd(totalSpend)
7028
- }
7029
- ),
7030
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 10.5 }, children: "month to date" })
7031
- ] });
7032
- };
7033
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7034
- import_Box19.default,
7035
- {
7036
- sx: {
7037
- display: "flex",
7038
- flexDirection: "column",
7039
- alignItems: "center",
7040
- minWidth: 0
7041
- },
7042
- role: "img",
7043
- "aria-label": sparklineAriaLabel(data),
7044
- children: [
7045
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { height, width: "100%" }, children: renderPlot() }),
7046
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7047
- import_Typography17.default,
7048
- {
7049
- sx: (theme) => ({
7050
- mt: 0.75,
7051
- fontSize: 10.5,
7052
- fontWeight: 700,
7053
- letterSpacing: "0.08em",
7054
- textTransform: "uppercase",
7055
- color: theme.palette.text.secondary
7056
- }),
7057
- children: "Spend (MTD)"
7058
- }
7059
- ),
7060
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7061
- import_Typography17.default,
7062
- {
7063
- variant: "caption",
7064
- color: "text.secondary",
7065
- sx: { mt: 0.25, fontSize: 10.5 },
7066
- children: mtdCaption()
7067
- }
7068
- ),
7069
- renderCaption()
7070
- ]
7071
- }
7072
- );
7117
+ const caption = (() => {
7118
+ if (loading) return "\u2026";
7119
+ if (usageUnavailable) return USAGE_UNAVAILABLE_MSG;
7120
+ if (data.length === 0) return "No spend this month";
7121
+ return mtdCaption();
7122
+ })();
7123
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { role: "img", "aria-label": sparklineAriaLabel(data), sx: { minWidth: 0 }, children: [
7124
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { height, width: "100%" }, children: renderPlot() }),
7125
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7126
+ import_Box19.default,
7127
+ {
7128
+ sx: {
7129
+ display: "flex",
7130
+ alignItems: "baseline",
7131
+ justifyContent: "space-between",
7132
+ gap: 1,
7133
+ mt: 0.5,
7134
+ minWidth: 0
7135
+ },
7136
+ children: [
7137
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "baseline", gap: 0.75, minWidth: 0 }, children: [
7138
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { children: "Spent (mtd)" }),
7139
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7140
+ import_Typography17.default,
7141
+ {
7142
+ variant: "caption",
7143
+ color: "text.secondary",
7144
+ sx: { fontSize: 10.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
7145
+ children: caption
7146
+ }
7147
+ )
7148
+ ] }),
7149
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7150
+ import_Typography17.default,
7151
+ {
7152
+ title: loading || usageUnavailable ? void 0 : `${fmtUsd(mtdSpend)} spent month to date`,
7153
+ sx: {
7154
+ fontSize: 12.5,
7155
+ fontWeight: 700,
7156
+ fontVariantNumeric: "tabular-nums",
7157
+ whiteSpace: "nowrap"
7158
+ },
7159
+ children: loading || usageUnavailable ? "\u2014" : fmtUsd(mtdSpend)
7160
+ }
7161
+ )
7162
+ ]
7163
+ }
7164
+ )
7165
+ ] });
7073
7166
  };
7167
+ function statValue(loading, unavailable, value) {
7168
+ if (loading) return "\u2026";
7169
+ if (unavailable) return "\u2014";
7170
+ return value;
7171
+ }
7172
+ function statHint(loading, unavailable, hint) {
7173
+ if (loading) return void 0;
7174
+ if (unavailable) return USAGE_UNAVAILABLE_MSG;
7175
+ return hint;
7176
+ }
7074
7177
  var LiteLLMBudgetGauges = ({
7075
7178
  title = "Budget",
7076
7179
  bare = false,
7077
- size = 72,
7180
+ size = 56,
7078
7181
  keysHref,
7079
7182
  moduleHref: propModuleHref,
7080
7183
  onCreateKey,
@@ -7091,7 +7194,7 @@ var LiteLLMBudgetGauges = ({
7091
7194
  const api = (0, import_core_plugin_api7.useApi)(liteLlmApiRef);
7092
7195
  const theme = (0, import_styles13.useTheme)();
7093
7196
  const isSmallScreen = (0, import_useMediaQuery.default)(theme.breakpoints.down("sm"));
7094
- const gaugeSize = isSmallScreen ? 56 : size;
7197
+ const gaugeSize = isSmallScreen ? Math.min(48, size) : size;
7095
7198
  const expandedRegionId = (0, import_react15.useId)();
7096
7199
  const moduleRouteRef = (0, import_frontend_plugin_api6.useRouteRef)(rootRouteRef);
7097
7200
  const moduleHref = propModuleHref ?? moduleRouteRef?.();
@@ -7166,6 +7269,12 @@ var LiteLLMBudgetGauges = ({
7166
7269
  }),
7167
7270
  [loading, profileError, user, usageError, keys]
7168
7271
  );
7272
+ const today = /* @__PURE__ */ new Date();
7273
+ const todaySpend = spendOnDay(dailySpend, today);
7274
+ const yesterday = new Date(today);
7275
+ yesterday.setDate(yesterday.getDate() - 1);
7276
+ const yesterdaySpend = dailySpend.some((d) => d.date === toLocalDay(yesterday)) ? spendOnDay(dailySpend, yesterday) : null;
7277
+ const todayHint = yesterdaySpend === null ? void 0 : `vs ${fmtUsd(yesterdaySpend)} yesterday`;
7169
7278
  const summaryText = headline.count === 0 ? "no limits apply" : `${headline.count} limit${headline.count === 1 ? "" : "s"}`;
7170
7279
  const resolvedCtas = (0, import_react15.useMemo)(() => {
7171
7280
  return resolveCtas({
@@ -7226,29 +7335,70 @@ var LiteLLMBudgetGauges = ({
7226
7335
  }
7227
7336
  )
7228
7337
  ] }),
7229
- viewState.kind === "loading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { display: "flex", alignItems: "flex-start", gap: 1, minHeight: size }, children: [0, 1, 2, 3].map((i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", flexDirection: "column", alignItems: "center", flex: 1 }, children: [
7230
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "circular", width: size, height: size, sx: { mb: 0.75 } }),
7231
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "100%", height: 12, sx: { mb: 0.25 } }),
7232
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "80%", height: 11, sx: { mb: 0.25 } }),
7233
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "70%", height: 10.5 })
7338
+ viewState.kind === "loading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { display: "flex", flexDirection: "column", gap: 1.25, minHeight: size }, children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "center", gap: 1.25 }, children: [
7339
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "circular", width: size, height: size }),
7340
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { flex: 1 }, children: [
7341
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "70%", height: 12, sx: { mb: 0.25 } }),
7342
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "45%", height: 11 })
7343
+ ] }),
7344
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: 64, height: 12 })
7234
7345
  ] }, i)) }),
7235
7346
  viewState.kind === "error" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: viewState.message }),
7236
7347
  viewState.kind === "unprovisioned" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: UNPROVISIONED_MSG }),
7237
7348
  viewState.kind === "ready" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
7238
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(76px, 1fr))", gap: 1 }, children: [
7239
- gauges.map((gauge) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LevelGauge, { gauge, size: gaugeSize, keysHref: keysTabHref }, gauge.kind)),
7240
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7241
- UsageMiniChart,
7242
- {
7243
- data: dailySpend,
7244
- totalSpend: mtdSpend,
7245
- loading: usageLoading,
7246
- height: gaugeSize,
7247
- usageUnavailable: viewState.usageUnavailable,
7248
- maxBudget: user?.max_budget ?? void 0
7249
- }
7250
- )
7251
- ] }),
7349
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7350
+ import_Box19.default,
7351
+ {
7352
+ sx: {
7353
+ display: "flex",
7354
+ alignItems: "stretch",
7355
+ gap: 2,
7356
+ mb: 1.25,
7357
+ minWidth: 0
7358
+ },
7359
+ children: [
7360
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7361
+ InlineStat,
7362
+ {
7363
+ label: "Today spent",
7364
+ tone: "accent",
7365
+ value: statValue(usageLoading, viewState.usageUnavailable, fmtUsd(todaySpend)),
7366
+ hint: statHint(usageLoading, viewState.usageUnavailable, todayHint),
7367
+ title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend since local midnight"
7368
+ }
7369
+ ),
7370
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { width: "1px", bgcolor: "divider", flexShrink: 0 } }),
7371
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7372
+ InlineStat,
7373
+ {
7374
+ label: "Month to date",
7375
+ value: statValue(usageLoading, viewState.usageUnavailable, fmtUsd(mtdSpend)),
7376
+ hint: statHint(usageLoading, viewState.usageUnavailable, mtdCaption()),
7377
+ title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend from the 1st of this month"
7378
+ }
7379
+ )
7380
+ ]
7381
+ }
7382
+ ),
7383
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { borderTop: "1px solid", borderColor: "divider" }, children: gauges.map((gauge, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7384
+ import_Box19.default,
7385
+ {
7386
+ sx: i === 0 ? void 0 : { borderTop: "1px solid", borderColor: "divider" },
7387
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LevelRow, { gauge, size: gaugeSize, keysHref: keysTabHref })
7388
+ },
7389
+ gauge.kind
7390
+ )) }),
7391
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { mt: 1.25 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7392
+ SpendStrip,
7393
+ {
7394
+ data: dailySpend,
7395
+ mtdSpend,
7396
+ loading: usageLoading,
7397
+ height: gaugeSize,
7398
+ usageUnavailable: viewState.usageUnavailable,
7399
+ maxBudget: user?.max_budget ?? void 0
7400
+ }
7401
+ ) }),
7252
7402
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Collapse4.default, { in: isExpanded, unmountOnExit: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7253
7403
  import_Box19.default,
7254
7404
  {