@almadar/ui 4.19.3 → 4.20.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.
@@ -7093,7 +7093,7 @@ var init_RangeSlider = __esm({
7093
7093
  action,
7094
7094
  actionPayload,
7095
7095
  onChange,
7096
- formatValue: formatValue5,
7096
+ formatValue: formatValue4,
7097
7097
  ...props
7098
7098
  }, ref) => {
7099
7099
  const [isDragging, setIsDragging] = React127.useState(false);
@@ -7102,7 +7102,7 @@ var init_RangeSlider = __esm({
7102
7102
  const eventBus = useSafeEventBus();
7103
7103
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
7104
7104
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
7105
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
7105
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
7106
7106
  const handleChange = React127.useCallback(
7107
7107
  (e) => {
7108
7108
  const newValue = Number(e.target.value);
@@ -27444,25 +27444,24 @@ var init_Lightbox = __esm({
27444
27444
  Lightbox.displayName = "Lightbox";
27445
27445
  }
27446
27446
  });
27447
- function formatValue3(value, format, max) {
27447
+ function formatNumber(value, format) {
27448
27448
  if (value == null) return "0";
27449
27449
  const v = typeof value === "number" ? value : value;
27450
- let formatted;
27451
27450
  switch (format) {
27452
27451
  case "currency":
27453
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
27454
- break;
27452
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
27455
27453
  case "percent":
27456
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
27457
- break;
27454
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
27458
27455
  case "number":
27459
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
27460
- break;
27456
+ return typeof v === "number" ? v.toLocaleString() : String(v);
27461
27457
  default:
27462
- formatted = String(v);
27458
+ return String(v);
27463
27459
  }
27464
- if (max != null) return `${formatted} / ${max}`;
27465
- return formatted;
27460
+ }
27461
+ function composeDisplayValue(value, format, max, prefix, suffix) {
27462
+ const formatted = formatNumber(value, format);
27463
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
27464
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
27466
27465
  }
27467
27466
  var variantColor, StatDisplay;
27468
27467
  var init_StatDisplay = __esm({
@@ -27486,6 +27485,10 @@ var init_StatDisplay = __esm({
27486
27485
  label,
27487
27486
  value,
27488
27487
  max,
27488
+ target,
27489
+ trend,
27490
+ prefix,
27491
+ suffix,
27489
27492
  icon: iconProp,
27490
27493
  iconBg = "bg-muted",
27491
27494
  iconColor = "text-foreground",
@@ -27501,7 +27504,13 @@ var init_StatDisplay = __esm({
27501
27504
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
27502
27505
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
27503
27506
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
27504
- const displayValue = formatValue3(value, format, max);
27507
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
27508
+ const numericValue = typeof value === "number" ? value : Number(value);
27509
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
27510
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
27511
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
27512
+ const trendUp = showTrend && trend > 0;
27513
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
27505
27514
  if (error) {
27506
27515
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "error", children: error.message }) });
27507
27516
  }
@@ -27516,13 +27525,31 @@ var init_StatDisplay = __esm({
27516
27525
  ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
27517
27526
  typeof iconProp !== "string" && iconProp,
27518
27527
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
27519
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
27528
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
27529
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
27520
27530
  ] });
27521
27531
  }
27522
27532
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
27523
- /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1", children: [
27533
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
27524
27534
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
27525
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
27535
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
27536
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
27537
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(
27538
+ Typography,
27539
+ {
27540
+ variant: "caption",
27541
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
27542
+ children: trendLabel
27543
+ }
27544
+ )
27545
+ ] }),
27546
+ showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
27547
+ Box,
27548
+ {
27549
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
27550
+ style: { width: `${targetPct}%` }
27551
+ }
27552
+ ) })
27526
27553
  ] }),
27527
27554
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
27528
27555
  ] }) });
@@ -33683,7 +33710,7 @@ function getStatusStyle(fieldName, value) {
33683
33710
  if (val.includes("low")) return STATUS_STYLES2.low;
33684
33711
  return STATUS_STYLES2.default;
33685
33712
  }
33686
- function formatValue4(value, fieldName) {
33713
+ function formatValue3(value, fieldName) {
33687
33714
  if (typeof value === "number") {
33688
33715
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
33689
33716
  return `${value}%`;
@@ -34059,7 +34086,7 @@ var init_List = __esm({
34059
34086
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
34060
34087
  children: [
34061
34088
  /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Calendar, { className: "w-3.5 h-3.5" }),
34062
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: formatValue4(value, field) })
34089
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: formatValue3(value, field) })
34063
34090
  ]
34064
34091
  },
34065
34092
  field
@@ -34078,7 +34105,7 @@ var init_List = __esm({
34078
34105
  formatFieldLabel2(field),
34079
34106
  ":"
34080
34107
  ] }),
34081
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
34108
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
34082
34109
  ]
34083
34110
  },
34084
34111
  field
@@ -51638,7 +51665,6 @@ function getSlotContentRenderer2() {
51638
51665
  }
51639
51666
  function makeLambdaFn(argName, lambdaBody, callerKey) {
51640
51667
  return (item, index) => {
51641
- console.log(`[lambda-triage:${callerKey}#${index}]`, JSON.stringify(item));
51642
51668
  const resolvedBody = resolveLambdaBindings(lambdaBody, argName, item);
51643
51669
  if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody)) {
51644
51670
  return null;
package/dist/avl/index.js CHANGED
@@ -7047,7 +7047,7 @@ var init_RangeSlider = __esm({
7047
7047
  action,
7048
7048
  actionPayload,
7049
7049
  onChange,
7050
- formatValue: formatValue5,
7050
+ formatValue: formatValue4,
7051
7051
  ...props
7052
7052
  }, ref) => {
7053
7053
  const [isDragging, setIsDragging] = useState(false);
@@ -7056,7 +7056,7 @@ var init_RangeSlider = __esm({
7056
7056
  const eventBus = useSafeEventBus();
7057
7057
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
7058
7058
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
7059
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
7059
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
7060
7060
  const handleChange = useCallback(
7061
7061
  (e) => {
7062
7062
  const newValue = Number(e.target.value);
@@ -27398,25 +27398,24 @@ var init_Lightbox = __esm({
27398
27398
  Lightbox.displayName = "Lightbox";
27399
27399
  }
27400
27400
  });
27401
- function formatValue3(value, format, max) {
27401
+ function formatNumber(value, format) {
27402
27402
  if (value == null) return "0";
27403
27403
  const v = typeof value === "number" ? value : value;
27404
- let formatted;
27405
27404
  switch (format) {
27406
27405
  case "currency":
27407
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
27408
- break;
27406
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
27409
27407
  case "percent":
27410
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
27411
- break;
27408
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
27412
27409
  case "number":
27413
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
27414
- break;
27410
+ return typeof v === "number" ? v.toLocaleString() : String(v);
27415
27411
  default:
27416
- formatted = String(v);
27412
+ return String(v);
27417
27413
  }
27418
- if (max != null) return `${formatted} / ${max}`;
27419
- return formatted;
27414
+ }
27415
+ function composeDisplayValue(value, format, max, prefix, suffix) {
27416
+ const formatted = formatNumber(value, format);
27417
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
27418
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
27420
27419
  }
27421
27420
  var variantColor, StatDisplay;
27422
27421
  var init_StatDisplay = __esm({
@@ -27440,6 +27439,10 @@ var init_StatDisplay = __esm({
27440
27439
  label,
27441
27440
  value,
27442
27441
  max,
27442
+ target,
27443
+ trend,
27444
+ prefix,
27445
+ suffix,
27443
27446
  icon: iconProp,
27444
27447
  iconBg = "bg-muted",
27445
27448
  iconColor = "text-foreground",
@@ -27455,7 +27458,13 @@ var init_StatDisplay = __esm({
27455
27458
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
27456
27459
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
27457
27460
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
27458
- const displayValue = formatValue3(value, format, max);
27461
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
27462
+ const numericValue = typeof value === "number" ? value : Number(value);
27463
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
27464
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
27465
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
27466
+ const trendUp = showTrend && trend > 0;
27467
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
27459
27468
  if (error) {
27460
27469
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsx(Typography, { variant: "small", color: "error", children: error.message }) });
27461
27470
  }
@@ -27470,13 +27479,31 @@ var init_StatDisplay = __esm({
27470
27479
  ResolvedIcon && /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
27471
27480
  typeof iconProp !== "string" && iconProp,
27472
27481
  /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: label }),
27473
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
27482
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
27483
+ showTrend && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
27474
27484
  ] });
27475
27485
  }
27476
27486
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxs(HStack, { align: "start", justify: "between", children: [
27477
- /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1", children: [
27487
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
27478
27488
  /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", children: label }),
27479
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
27489
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "end", children: [
27490
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
27491
+ showTrend && /* @__PURE__ */ jsx(
27492
+ Typography,
27493
+ {
27494
+ variant: "caption",
27495
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
27496
+ children: trendLabel
27497
+ }
27498
+ )
27499
+ ] }),
27500
+ showTarget && /* @__PURE__ */ jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
27501
+ Box,
27502
+ {
27503
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
27504
+ style: { width: `${targetPct}%` }
27505
+ }
27506
+ ) })
27480
27507
  ] }),
27481
27508
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
27482
27509
  ] }) });
@@ -33637,7 +33664,7 @@ function getStatusStyle(fieldName, value) {
33637
33664
  if (val.includes("low")) return STATUS_STYLES2.low;
33638
33665
  return STATUS_STYLES2.default;
33639
33666
  }
33640
- function formatValue4(value, fieldName) {
33667
+ function formatValue3(value, fieldName) {
33641
33668
  if (typeof value === "number") {
33642
33669
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
33643
33670
  return `${value}%`;
@@ -34013,7 +34040,7 @@ var init_List = __esm({
34013
34040
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
34014
34041
  children: [
34015
34042
  /* @__PURE__ */ jsx(Calendar, { className: "w-3.5 h-3.5" }),
34016
- /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue4(value, field) })
34043
+ /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue3(value, field) })
34017
34044
  ]
34018
34045
  },
34019
34046
  field
@@ -34032,7 +34059,7 @@ var init_List = __esm({
34032
34059
  formatFieldLabel2(field),
34033
34060
  ":"
34034
34061
  ] }),
34035
- /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
34062
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
34036
34063
  ]
34037
34064
  },
34038
34065
  field
@@ -51592,7 +51619,6 @@ function getSlotContentRenderer2() {
51592
51619
  }
51593
51620
  function makeLambdaFn(argName, lambdaBody, callerKey) {
51594
51621
  return (item, index) => {
51595
- console.log(`[lambda-triage:${callerKey}#${index}]`, JSON.stringify(item));
51596
51622
  const resolvedBody = resolveLambdaBindings(lambdaBody, argName, item);
51597
51623
  if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody)) {
51598
51624
  return null;
@@ -3017,7 +3017,7 @@ var init_RangeSlider = __esm({
3017
3017
  action,
3018
3018
  actionPayload,
3019
3019
  onChange,
3020
- formatValue: formatValue5,
3020
+ formatValue: formatValue4,
3021
3021
  ...props
3022
3022
  }, ref) => {
3023
3023
  const [isDragging, setIsDragging] = React110.useState(false);
@@ -3026,7 +3026,7 @@ var init_RangeSlider = __esm({
3026
3026
  const eventBus = useSafeEventBus();
3027
3027
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
3028
3028
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
3029
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
3029
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
3030
3030
  const handleChange = React110.useCallback(
3031
3031
  (e) => {
3032
3032
  const newValue = Number(e.target.value);
@@ -23142,25 +23142,24 @@ var init_Lightbox = __esm({
23142
23142
  exports.Lightbox.displayName = "Lightbox";
23143
23143
  }
23144
23144
  });
23145
- function formatValue3(value, format, max) {
23145
+ function formatNumber(value, format) {
23146
23146
  if (value == null) return "0";
23147
23147
  const v = typeof value === "number" ? value : value;
23148
- let formatted;
23149
23148
  switch (format) {
23150
23149
  case "currency":
23151
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23152
- break;
23150
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23153
23151
  case "percent":
23154
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
23155
- break;
23152
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
23156
23153
  case "number":
23157
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
23158
- break;
23154
+ return typeof v === "number" ? v.toLocaleString() : String(v);
23159
23155
  default:
23160
- formatted = String(v);
23156
+ return String(v);
23161
23157
  }
23162
- if (max != null) return `${formatted} / ${max}`;
23163
- return formatted;
23158
+ }
23159
+ function composeDisplayValue(value, format, max, prefix, suffix) {
23160
+ const formatted = formatNumber(value, format);
23161
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
23162
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
23164
23163
  }
23165
23164
  var variantColor; exports.StatDisplay = void 0;
23166
23165
  var init_StatDisplay = __esm({
@@ -23184,6 +23183,10 @@ var init_StatDisplay = __esm({
23184
23183
  label,
23185
23184
  value,
23186
23185
  max,
23186
+ target,
23187
+ trend,
23188
+ prefix,
23189
+ suffix,
23187
23190
  icon: iconProp,
23188
23191
  iconBg = "bg-muted",
23189
23192
  iconColor = "text-foreground",
@@ -23199,7 +23202,13 @@ var init_StatDisplay = __esm({
23199
23202
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
23200
23203
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
23201
23204
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
23202
- const displayValue = formatValue3(value, format, max);
23205
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
23206
+ const numericValue = typeof value === "number" ? value : Number(value);
23207
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
23208
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
23209
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
23210
+ const trendUp = showTrend && trend > 0;
23211
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
23203
23212
  if (error) {
23204
23213
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "error", children: error.message }) });
23205
23214
  }
@@ -23214,13 +23223,31 @@ var init_StatDisplay = __esm({
23214
23223
  ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
23215
23224
  typeof iconProp !== "string" && iconProp,
23216
23225
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: label }),
23217
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23226
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
23227
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
23218
23228
  ] });
23219
23229
  }
23220
23230
  return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { align: "start", justify: "between", children: [
23221
- /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "none", className: "space-y-1", children: [
23231
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "none", className: "space-y-1 flex-1", children: [
23222
23232
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "overline", color: "secondary", children: label }),
23223
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23233
+ /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", align: "end", children: [
23234
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
23235
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(
23236
+ exports.Typography,
23237
+ {
23238
+ variant: "caption",
23239
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
23240
+ children: trendLabel
23241
+ }
23242
+ )
23243
+ ] }),
23244
+ showTarget && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
23245
+ exports.Box,
23246
+ {
23247
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
23248
+ style: { width: `${targetPct}%` }
23249
+ }
23250
+ ) })
23224
23251
  ] }),
23225
23252
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
23226
23253
  ] }) });
@@ -29476,7 +29503,7 @@ function getStatusStyle(fieldName, value) {
29476
29503
  if (val.includes("low")) return STATUS_STYLES2.low;
29477
29504
  return STATUS_STYLES2.default;
29478
29505
  }
29479
- function formatValue4(value, fieldName) {
29506
+ function formatValue3(value, fieldName) {
29480
29507
  if (typeof value === "number") {
29481
29508
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
29482
29509
  return `${value}%`;
@@ -29852,7 +29879,7 @@ var init_List = __esm({
29852
29879
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
29853
29880
  children: [
29854
29881
  /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Calendar, { className: "w-3.5 h-3.5" }),
29855
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", children: formatValue4(value, field) })
29882
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", children: formatValue3(value, field) })
29856
29883
  ]
29857
29884
  },
29858
29885
  field
@@ -29871,7 +29898,7 @@ var init_List = __esm({
29871
29898
  formatFieldLabel2(field),
29872
29899
  ":"
29873
29900
  ] }),
29874
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
29901
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
29875
29902
  ]
29876
29903
  },
29877
29904
  field
@@ -2972,7 +2972,7 @@ var init_RangeSlider = __esm({
2972
2972
  action,
2973
2973
  actionPayload,
2974
2974
  onChange,
2975
- formatValue: formatValue5,
2975
+ formatValue: formatValue4,
2976
2976
  ...props
2977
2977
  }, ref) => {
2978
2978
  const [isDragging, setIsDragging] = useState(false);
@@ -2981,7 +2981,7 @@ var init_RangeSlider = __esm({
2981
2981
  const eventBus = useSafeEventBus();
2982
2982
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
2983
2983
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
2984
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
2984
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
2985
2985
  const handleChange = useCallback(
2986
2986
  (e) => {
2987
2987
  const newValue = Number(e.target.value);
@@ -23097,25 +23097,24 @@ var init_Lightbox = __esm({
23097
23097
  Lightbox.displayName = "Lightbox";
23098
23098
  }
23099
23099
  });
23100
- function formatValue3(value, format, max) {
23100
+ function formatNumber(value, format) {
23101
23101
  if (value == null) return "0";
23102
23102
  const v = typeof value === "number" ? value : value;
23103
- let formatted;
23104
23103
  switch (format) {
23105
23104
  case "currency":
23106
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23107
- break;
23105
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23108
23106
  case "percent":
23109
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
23110
- break;
23107
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
23111
23108
  case "number":
23112
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
23113
- break;
23109
+ return typeof v === "number" ? v.toLocaleString() : String(v);
23114
23110
  default:
23115
- formatted = String(v);
23111
+ return String(v);
23116
23112
  }
23117
- if (max != null) return `${formatted} / ${max}`;
23118
- return formatted;
23113
+ }
23114
+ function composeDisplayValue(value, format, max, prefix, suffix) {
23115
+ const formatted = formatNumber(value, format);
23116
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
23117
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
23119
23118
  }
23120
23119
  var variantColor, StatDisplay;
23121
23120
  var init_StatDisplay = __esm({
@@ -23139,6 +23138,10 @@ var init_StatDisplay = __esm({
23139
23138
  label,
23140
23139
  value,
23141
23140
  max,
23141
+ target,
23142
+ trend,
23143
+ prefix,
23144
+ suffix,
23142
23145
  icon: iconProp,
23143
23146
  iconBg = "bg-muted",
23144
23147
  iconColor = "text-foreground",
@@ -23154,7 +23157,13 @@ var init_StatDisplay = __esm({
23154
23157
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
23155
23158
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
23156
23159
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
23157
- const displayValue = formatValue3(value, format, max);
23160
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
23161
+ const numericValue = typeof value === "number" ? value : Number(value);
23162
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
23163
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
23164
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
23165
+ const trendUp = showTrend && trend > 0;
23166
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
23158
23167
  if (error) {
23159
23168
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsx(Typography, { variant: "small", color: "error", children: error.message }) });
23160
23169
  }
@@ -23169,13 +23178,31 @@ var init_StatDisplay = __esm({
23169
23178
  ResolvedIcon && /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
23170
23179
  typeof iconProp !== "string" && iconProp,
23171
23180
  /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: label }),
23172
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23181
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
23182
+ showTrend && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
23173
23183
  ] });
23174
23184
  }
23175
23185
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxs(HStack, { align: "start", justify: "between", children: [
23176
- /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1", children: [
23186
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
23177
23187
  /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", children: label }),
23178
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23188
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "end", children: [
23189
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
23190
+ showTrend && /* @__PURE__ */ jsx(
23191
+ Typography,
23192
+ {
23193
+ variant: "caption",
23194
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
23195
+ children: trendLabel
23196
+ }
23197
+ )
23198
+ ] }),
23199
+ showTarget && /* @__PURE__ */ jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
23200
+ Box,
23201
+ {
23202
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
23203
+ style: { width: `${targetPct}%` }
23204
+ }
23205
+ ) })
23179
23206
  ] }),
23180
23207
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
23181
23208
  ] }) });
@@ -29431,7 +29458,7 @@ function getStatusStyle(fieldName, value) {
29431
29458
  if (val.includes("low")) return STATUS_STYLES2.low;
29432
29459
  return STATUS_STYLES2.default;
29433
29460
  }
29434
- function formatValue4(value, fieldName) {
29461
+ function formatValue3(value, fieldName) {
29435
29462
  if (typeof value === "number") {
29436
29463
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
29437
29464
  return `${value}%`;
@@ -29807,7 +29834,7 @@ var init_List = __esm({
29807
29834
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
29808
29835
  children: [
29809
29836
  /* @__PURE__ */ jsx(Calendar, { className: "w-3.5 h-3.5" }),
29810
- /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue4(value, field) })
29837
+ /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue3(value, field) })
29811
29838
  ]
29812
29839
  },
29813
29840
  field
@@ -29826,7 +29853,7 @@ var init_List = __esm({
29826
29853
  formatFieldLabel2(field),
29827
29854
  ":"
29828
29855
  ] }),
29829
- /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
29856
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
29830
29857
  ]
29831
29858
  },
29832
29859
  field
@@ -11,8 +11,16 @@ export interface StatDisplayProps {
11
11
  label: string;
12
12
  /** Primary value (number or formatted string) */
13
13
  value: number | string;
14
- /** Maximum value (renders as "value / max") */
14
+ /** Optional denominator. >0 renders "value / max"; 0 or omitted hides the divider. */
15
15
  max?: number;
16
+ /** Optional progress target. >0 renders a progress bar at value/target. */
17
+ target?: number;
18
+ /** Signed delta vs previous period. >0 renders ↑ green, <0 renders ↓ red, 0 hides. */
19
+ trend?: number;
20
+ /** Prefix prepended to the formatted value (e.g. "≈ "). */
21
+ prefix?: string;
22
+ /** Suffix appended to the formatted value (e.g. " /mo", " ms"). */
23
+ suffix?: string;
16
24
  /** Lucide icon name or React node */
17
25
  icon?: React.ReactNode;
18
26
  /** Icon background color class */
@@ -3539,7 +3539,7 @@ var init_RangeSlider = __esm({
3539
3539
  action,
3540
3540
  actionPayload,
3541
3541
  onChange,
3542
- formatValue: formatValue5,
3542
+ formatValue: formatValue4,
3543
3543
  ...props
3544
3544
  }, ref) => {
3545
3545
  const [isDragging, setIsDragging] = React115.useState(false);
@@ -3548,7 +3548,7 @@ var init_RangeSlider = __esm({
3548
3548
  const eventBus = useSafeEventBus();
3549
3549
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
3550
3550
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
3551
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
3551
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
3552
3552
  const handleChange = React115.useCallback(
3553
3553
  (e) => {
3554
3554
  const newValue = Number(e.target.value);
@@ -24195,25 +24195,24 @@ var init_Lightbox = __esm({
24195
24195
  Lightbox.displayName = "Lightbox";
24196
24196
  }
24197
24197
  });
24198
- function formatValue3(value, format, max) {
24198
+ function formatNumber(value, format) {
24199
24199
  if (value == null) return "0";
24200
24200
  const v = typeof value === "number" ? value : value;
24201
- let formatted;
24202
24201
  switch (format) {
24203
24202
  case "currency":
24204
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
24205
- break;
24203
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
24206
24204
  case "percent":
24207
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
24208
- break;
24205
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
24209
24206
  case "number":
24210
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
24211
- break;
24207
+ return typeof v === "number" ? v.toLocaleString() : String(v);
24212
24208
  default:
24213
- formatted = String(v);
24209
+ return String(v);
24214
24210
  }
24215
- if (max != null) return `${formatted} / ${max}`;
24216
- return formatted;
24211
+ }
24212
+ function composeDisplayValue(value, format, max, prefix, suffix) {
24213
+ const formatted = formatNumber(value, format);
24214
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
24215
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
24217
24216
  }
24218
24217
  var variantColor, StatDisplay;
24219
24218
  var init_StatDisplay = __esm({
@@ -24237,6 +24236,10 @@ var init_StatDisplay = __esm({
24237
24236
  label,
24238
24237
  value,
24239
24238
  max,
24239
+ target,
24240
+ trend,
24241
+ prefix,
24242
+ suffix,
24240
24243
  icon: iconProp,
24241
24244
  iconBg = "bg-muted",
24242
24245
  iconColor = "text-foreground",
@@ -24252,7 +24255,13 @@ var init_StatDisplay = __esm({
24252
24255
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
24253
24256
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
24254
24257
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
24255
- const displayValue = formatValue3(value, format, max);
24258
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
24259
+ const numericValue = typeof value === "number" ? value : Number(value);
24260
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
24261
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
24262
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
24263
+ const trendUp = showTrend && trend > 0;
24264
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
24256
24265
  if (error) {
24257
24266
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "error", children: error.message }) });
24258
24267
  }
@@ -24267,13 +24276,31 @@ var init_StatDisplay = __esm({
24267
24276
  ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
24268
24277
  typeof iconProp !== "string" && iconProp,
24269
24278
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
24270
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
24279
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
24280
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
24271
24281
  ] });
24272
24282
  }
24273
24283
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
24274
- /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1", children: [
24284
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
24275
24285
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
24276
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
24286
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
24287
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
24288
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(
24289
+ Typography,
24290
+ {
24291
+ variant: "caption",
24292
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
24293
+ children: trendLabel
24294
+ }
24295
+ )
24296
+ ] }),
24297
+ showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
24298
+ Box,
24299
+ {
24300
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
24301
+ style: { width: `${targetPct}%` }
24302
+ }
24303
+ ) })
24277
24304
  ] }),
24278
24305
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
24279
24306
  ] }) });
@@ -30434,7 +30461,7 @@ function getStatusStyle(fieldName, value) {
30434
30461
  if (val.includes("low")) return STATUS_STYLES2.low;
30435
30462
  return STATUS_STYLES2.default;
30436
30463
  }
30437
- function formatValue4(value, fieldName) {
30464
+ function formatValue3(value, fieldName) {
30438
30465
  if (typeof value === "number") {
30439
30466
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
30440
30467
  return `${value}%`;
@@ -30810,7 +30837,7 @@ var init_List = __esm({
30810
30837
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
30811
30838
  children: [
30812
30839
  /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Calendar, { className: "w-3.5 h-3.5" }),
30813
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: formatValue4(value, field) })
30840
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: formatValue3(value, field) })
30814
30841
  ]
30815
30842
  },
30816
30843
  field
@@ -30829,7 +30856,7 @@ var init_List = __esm({
30829
30856
  formatFieldLabel2(field),
30830
30857
  ":"
30831
30858
  ] }),
30832
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
30859
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
30833
30860
  ]
30834
30861
  },
30835
30862
  field
@@ -3494,7 +3494,7 @@ var init_RangeSlider = __esm({
3494
3494
  action,
3495
3495
  actionPayload,
3496
3496
  onChange,
3497
- formatValue: formatValue5,
3497
+ formatValue: formatValue4,
3498
3498
  ...props
3499
3499
  }, ref) => {
3500
3500
  const [isDragging, setIsDragging] = useState(false);
@@ -3503,7 +3503,7 @@ var init_RangeSlider = __esm({
3503
3503
  const eventBus = useSafeEventBus();
3504
3504
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
3505
3505
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
3506
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
3506
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
3507
3507
  const handleChange = useCallback(
3508
3508
  (e) => {
3509
3509
  const newValue = Number(e.target.value);
@@ -24150,25 +24150,24 @@ var init_Lightbox = __esm({
24150
24150
  Lightbox.displayName = "Lightbox";
24151
24151
  }
24152
24152
  });
24153
- function formatValue3(value, format, max) {
24153
+ function formatNumber(value, format) {
24154
24154
  if (value == null) return "0";
24155
24155
  const v = typeof value === "number" ? value : value;
24156
- let formatted;
24157
24156
  switch (format) {
24158
24157
  case "currency":
24159
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
24160
- break;
24158
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
24161
24159
  case "percent":
24162
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
24163
- break;
24160
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
24164
24161
  case "number":
24165
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
24166
- break;
24162
+ return typeof v === "number" ? v.toLocaleString() : String(v);
24167
24163
  default:
24168
- formatted = String(v);
24164
+ return String(v);
24169
24165
  }
24170
- if (max != null) return `${formatted} / ${max}`;
24171
- return formatted;
24166
+ }
24167
+ function composeDisplayValue(value, format, max, prefix, suffix) {
24168
+ const formatted = formatNumber(value, format);
24169
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
24170
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
24172
24171
  }
24173
24172
  var variantColor, StatDisplay;
24174
24173
  var init_StatDisplay = __esm({
@@ -24192,6 +24191,10 @@ var init_StatDisplay = __esm({
24192
24191
  label,
24193
24192
  value,
24194
24193
  max,
24194
+ target,
24195
+ trend,
24196
+ prefix,
24197
+ suffix,
24195
24198
  icon: iconProp,
24196
24199
  iconBg = "bg-muted",
24197
24200
  iconColor = "text-foreground",
@@ -24207,7 +24210,13 @@ var init_StatDisplay = __esm({
24207
24210
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
24208
24211
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
24209
24212
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
24210
- const displayValue = formatValue3(value, format, max);
24213
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
24214
+ const numericValue = typeof value === "number" ? value : Number(value);
24215
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
24216
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
24217
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
24218
+ const trendUp = showTrend && trend > 0;
24219
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
24211
24220
  if (error) {
24212
24221
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsx(Typography, { variant: "small", color: "error", children: error.message }) });
24213
24222
  }
@@ -24222,13 +24231,31 @@ var init_StatDisplay = __esm({
24222
24231
  ResolvedIcon && /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
24223
24232
  typeof iconProp !== "string" && iconProp,
24224
24233
  /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: label }),
24225
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
24234
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
24235
+ showTrend && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
24226
24236
  ] });
24227
24237
  }
24228
24238
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxs(HStack, { align: "start", justify: "between", children: [
24229
- /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1", children: [
24239
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
24230
24240
  /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", children: label }),
24231
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
24241
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "end", children: [
24242
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
24243
+ showTrend && /* @__PURE__ */ jsx(
24244
+ Typography,
24245
+ {
24246
+ variant: "caption",
24247
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
24248
+ children: trendLabel
24249
+ }
24250
+ )
24251
+ ] }),
24252
+ showTarget && /* @__PURE__ */ jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
24253
+ Box,
24254
+ {
24255
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
24256
+ style: { width: `${targetPct}%` }
24257
+ }
24258
+ ) })
24232
24259
  ] }),
24233
24260
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
24234
24261
  ] }) });
@@ -30389,7 +30416,7 @@ function getStatusStyle(fieldName, value) {
30389
30416
  if (val.includes("low")) return STATUS_STYLES2.low;
30390
30417
  return STATUS_STYLES2.default;
30391
30418
  }
30392
- function formatValue4(value, fieldName) {
30419
+ function formatValue3(value, fieldName) {
30393
30420
  if (typeof value === "number") {
30394
30421
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
30395
30422
  return `${value}%`;
@@ -30765,7 +30792,7 @@ var init_List = __esm({
30765
30792
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
30766
30793
  children: [
30767
30794
  /* @__PURE__ */ jsx(Calendar, { className: "w-3.5 h-3.5" }),
30768
- /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue4(value, field) })
30795
+ /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue3(value, field) })
30769
30796
  ]
30770
30797
  },
30771
30798
  field
@@ -30784,7 +30811,7 @@ var init_List = __esm({
30784
30811
  formatFieldLabel2(field),
30785
30812
  ":"
30786
30813
  ] }),
30787
- /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
30814
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
30788
30815
  ]
30789
30816
  },
30790
30817
  field
@@ -3951,7 +3951,7 @@ var init_RangeSlider = __esm({
3951
3951
  action,
3952
3952
  actionPayload,
3953
3953
  onChange,
3954
- formatValue: formatValue5,
3954
+ formatValue: formatValue4,
3955
3955
  ...props
3956
3956
  }, ref) => {
3957
3957
  const [isDragging, setIsDragging] = React113.useState(false);
@@ -3960,7 +3960,7 @@ var init_RangeSlider = __esm({
3960
3960
  const eventBus = useSafeEventBus();
3961
3961
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
3962
3962
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
3963
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
3963
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
3964
3964
  const handleChange = React113.useCallback(
3965
3965
  (e) => {
3966
3966
  const newValue = Number(e.target.value);
@@ -23907,25 +23907,24 @@ var init_Lightbox = __esm({
23907
23907
  Lightbox.displayName = "Lightbox";
23908
23908
  }
23909
23909
  });
23910
- function formatValue3(value, format, max) {
23910
+ function formatNumber(value, format) {
23911
23911
  if (value == null) return "0";
23912
23912
  const v = typeof value === "number" ? value : value;
23913
- let formatted;
23914
23913
  switch (format) {
23915
23914
  case "currency":
23916
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23917
- break;
23915
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23918
23916
  case "percent":
23919
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
23920
- break;
23917
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
23921
23918
  case "number":
23922
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
23923
- break;
23919
+ return typeof v === "number" ? v.toLocaleString() : String(v);
23924
23920
  default:
23925
- formatted = String(v);
23921
+ return String(v);
23926
23922
  }
23927
- if (max != null) return `${formatted} / ${max}`;
23928
- return formatted;
23923
+ }
23924
+ function composeDisplayValue(value, format, max, prefix, suffix) {
23925
+ const formatted = formatNumber(value, format);
23926
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
23927
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
23929
23928
  }
23930
23929
  var variantColor, StatDisplay;
23931
23930
  var init_StatDisplay = __esm({
@@ -23949,6 +23948,10 @@ var init_StatDisplay = __esm({
23949
23948
  label,
23950
23949
  value,
23951
23950
  max,
23951
+ target,
23952
+ trend,
23953
+ prefix,
23954
+ suffix,
23952
23955
  icon: iconProp,
23953
23956
  iconBg = "bg-muted",
23954
23957
  iconColor = "text-foreground",
@@ -23964,7 +23967,13 @@ var init_StatDisplay = __esm({
23964
23967
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
23965
23968
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
23966
23969
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
23967
- const displayValue = formatValue3(value, format, max);
23970
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
23971
+ const numericValue = typeof value === "number" ? value : Number(value);
23972
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
23973
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
23974
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
23975
+ const trendUp = showTrend && trend > 0;
23976
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
23968
23977
  if (error) {
23969
23978
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "error", children: error.message }) });
23970
23979
  }
@@ -23979,13 +23988,31 @@ var init_StatDisplay = __esm({
23979
23988
  ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
23980
23989
  typeof iconProp !== "string" && iconProp,
23981
23990
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
23982
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23991
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
23992
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
23983
23993
  ] });
23984
23994
  }
23985
23995
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
23986
- /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1", children: [
23996
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
23987
23997
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
23988
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23998
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
23999
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
24000
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(
24001
+ Typography,
24002
+ {
24003
+ variant: "caption",
24004
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
24005
+ children: trendLabel
24006
+ }
24007
+ )
24008
+ ] }),
24009
+ showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
24010
+ Box,
24011
+ {
24012
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
24013
+ style: { width: `${targetPct}%` }
24014
+ }
24015
+ ) })
23989
24016
  ] }),
23990
24017
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
23991
24018
  ] }) });
@@ -30008,7 +30035,7 @@ function getStatusStyle(fieldName, value) {
30008
30035
  if (val.includes("low")) return STATUS_STYLES2.low;
30009
30036
  return STATUS_STYLES2.default;
30010
30037
  }
30011
- function formatValue4(value, fieldName) {
30038
+ function formatValue3(value, fieldName) {
30012
30039
  if (typeof value === "number") {
30013
30040
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
30014
30041
  return `${value}%`;
@@ -30384,7 +30411,7 @@ var init_List = __esm({
30384
30411
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
30385
30412
  children: [
30386
30413
  /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Calendar, { className: "w-3.5 h-3.5" }),
30387
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: formatValue4(value, field) })
30414
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: formatValue3(value, field) })
30388
30415
  ]
30389
30416
  },
30390
30417
  field
@@ -30403,7 +30430,7 @@ var init_List = __esm({
30403
30430
  formatFieldLabel2(field),
30404
30431
  ":"
30405
30432
  ] }),
30406
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
30433
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
30407
30434
  ]
30408
30435
  },
30409
30436
  field
@@ -38229,7 +38256,6 @@ function getSlotContentRenderer2() {
38229
38256
  }
38230
38257
  function makeLambdaFn(argName, lambdaBody, callerKey) {
38231
38258
  return (item, index) => {
38232
- console.log(`[lambda-triage:${callerKey}#${index}]`, JSON.stringify(item));
38233
38259
  const resolvedBody = resolveLambdaBindings(lambdaBody, argName, item);
38234
38260
  if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody)) {
38235
38261
  return null;
@@ -3906,7 +3906,7 @@ var init_RangeSlider = __esm({
3906
3906
  action,
3907
3907
  actionPayload,
3908
3908
  onChange,
3909
- formatValue: formatValue5,
3909
+ formatValue: formatValue4,
3910
3910
  ...props
3911
3911
  }, ref) => {
3912
3912
  const [isDragging, setIsDragging] = useState(false);
@@ -3915,7 +3915,7 @@ var init_RangeSlider = __esm({
3915
3915
  const eventBus = useSafeEventBus();
3916
3916
  const percentage = max !== min ? (value - min) / (max - min) * 100 : 0;
3917
3917
  const bufferedPercentage = buffered !== void 0 ? Math.min(buffered, 100) : void 0;
3918
- const displayValue = formatValue5 ? formatValue5(value) : String(value);
3918
+ const displayValue = formatValue4 ? formatValue4(value) : String(value);
3919
3919
  const handleChange = useCallback(
3920
3920
  (e) => {
3921
3921
  const newValue = Number(e.target.value);
@@ -23862,25 +23862,24 @@ var init_Lightbox = __esm({
23862
23862
  Lightbox.displayName = "Lightbox";
23863
23863
  }
23864
23864
  });
23865
- function formatValue3(value, format, max) {
23865
+ function formatNumber(value, format) {
23866
23866
  if (value == null) return "0";
23867
23867
  const v = typeof value === "number" ? value : value;
23868
- let formatted;
23869
23868
  switch (format) {
23870
23869
  case "currency":
23871
- formatted = typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23872
- break;
23870
+ return typeof v === "number" ? `$${v.toFixed(2)}` : String(v);
23873
23871
  case "percent":
23874
- formatted = typeof v === "number" ? `${Math.round(v)}%` : String(v);
23875
- break;
23872
+ return typeof v === "number" ? `${Math.round(v)}%` : String(v);
23876
23873
  case "number":
23877
- formatted = typeof v === "number" ? v.toLocaleString() : String(v);
23878
- break;
23874
+ return typeof v === "number" ? v.toLocaleString() : String(v);
23879
23875
  default:
23880
- formatted = String(v);
23876
+ return String(v);
23881
23877
  }
23882
- if (max != null) return `${formatted} / ${max}`;
23883
- return formatted;
23878
+ }
23879
+ function composeDisplayValue(value, format, max, prefix, suffix) {
23880
+ const formatted = formatNumber(value, format);
23881
+ const withMax = max != null && max > 0 ? `${formatted} / ${max}` : formatted;
23882
+ return `${prefix ?? ""}${withMax}${suffix ?? ""}`;
23884
23883
  }
23885
23884
  var variantColor, StatDisplay;
23886
23885
  var init_StatDisplay = __esm({
@@ -23904,6 +23903,10 @@ var init_StatDisplay = __esm({
23904
23903
  label,
23905
23904
  value,
23906
23905
  max,
23906
+ target,
23907
+ trend,
23908
+ prefix,
23909
+ suffix,
23907
23910
  icon: iconProp,
23908
23911
  iconBg = "bg-muted",
23909
23912
  iconColor = "text-foreground",
@@ -23919,7 +23922,13 @@ var init_StatDisplay = __esm({
23919
23922
  const iconSizes2 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
23920
23923
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
23921
23924
  const padSizes = { sm: "p-3", md: "p-4", lg: "p-6" };
23922
- const displayValue = formatValue3(value, format, max);
23925
+ const displayValue = composeDisplayValue(value, format, max, prefix, suffix);
23926
+ const numericValue = typeof value === "number" ? value : Number(value);
23927
+ const showTarget = typeof target === "number" && target > 0 && Number.isFinite(numericValue);
23928
+ const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
23929
+ const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
23930
+ const trendUp = showTrend && trend > 0;
23931
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
23923
23932
  if (error) {
23924
23933
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsx(Typography, { variant: "small", color: "error", children: error.message }) });
23925
23934
  }
@@ -23934,13 +23943,31 @@ var init_StatDisplay = __esm({
23934
23943
  ResolvedIcon && /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }),
23935
23944
  typeof iconProp !== "string" && iconProp,
23936
23945
  /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: label }),
23937
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23946
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
23947
+ showTrend && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
23938
23948
  ] });
23939
23949
  }
23940
23950
  return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxs(HStack, { align: "start", justify: "between", children: [
23941
- /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1", children: [
23951
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
23942
23952
  /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", children: label }),
23943
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue })
23953
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "end", children: [
23954
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
23955
+ showTrend && /* @__PURE__ */ jsx(
23956
+ Typography,
23957
+ {
23958
+ variant: "caption",
23959
+ className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
23960
+ children: trendLabel
23961
+ }
23962
+ )
23963
+ ] }),
23964
+ showTarget && /* @__PURE__ */ jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
23965
+ Box,
23966
+ {
23967
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
23968
+ style: { width: `${targetPct}%` }
23969
+ }
23970
+ ) })
23944
23971
  ] }),
23945
23972
  (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes2[size], iconColor) }) : iconProp })
23946
23973
  ] }) });
@@ -29963,7 +29990,7 @@ function getStatusStyle(fieldName, value) {
29963
29990
  if (val.includes("low")) return STATUS_STYLES2.low;
29964
29991
  return STATUS_STYLES2.default;
29965
29992
  }
29966
- function formatValue4(value, fieldName) {
29993
+ function formatValue3(value, fieldName) {
29967
29994
  if (typeof value === "number") {
29968
29995
  if (fieldName.toLowerCase().includes("progress") || fieldName.toLowerCase().includes("percent")) {
29969
29996
  return `${value}%`;
@@ -30339,7 +30366,7 @@ var init_List = __esm({
30339
30366
  className: "flex items-center gap-2 text-muted-foreground group-hover:text-foreground transition-colors",
30340
30367
  children: [
30341
30368
  /* @__PURE__ */ jsx(Calendar, { className: "w-3.5 h-3.5" }),
30342
- /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue4(value, field) })
30369
+ /* @__PURE__ */ jsx(Typography, { as: "span", children: formatValue3(value, field) })
30343
30370
  ]
30344
30371
  },
30345
30372
  field
@@ -30358,7 +30385,7 @@ var init_List = __esm({
30358
30385
  formatFieldLabel2(field),
30359
30386
  ":"
30360
30387
  ] }),
30361
- /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue4(value, field) })
30388
+ /* @__PURE__ */ jsx(Typography, { as: "span", className: "text-foreground", children: formatValue3(value, field) })
30362
30389
  ]
30363
30390
  },
30364
30391
  field
@@ -38184,7 +38211,6 @@ function getSlotContentRenderer2() {
38184
38211
  }
38185
38212
  function makeLambdaFn(argName, lambdaBody, callerKey) {
38186
38213
  return (item, index) => {
38187
- console.log(`[lambda-triage:${callerKey}#${index}]`, JSON.stringify(item));
38188
38214
  const resolvedBody = resolveLambdaBindings(lambdaBody, argName, item);
38189
38215
  if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody)) {
38190
38216
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.19.3",
3
+ "version": "4.20.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",