@almadar/ui 4.51.13 → 4.51.15

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.
@@ -3649,6 +3649,67 @@ var init_Radio = __esm({
3649
3649
  Radio.displayName = "Radio";
3650
3650
  }
3651
3651
  });
3652
+ var COLOR_VAR, Sparkline;
3653
+ var init_Sparkline = __esm({
3654
+ "components/atoms/Sparkline.tsx"() {
3655
+ init_cn();
3656
+ COLOR_VAR = {
3657
+ primary: "var(--color-primary)",
3658
+ success: "var(--color-success)",
3659
+ warning: "var(--color-warning)",
3660
+ error: "var(--color-error)",
3661
+ info: "var(--color-info)",
3662
+ muted: "var(--color-muted-foreground)"
3663
+ };
3664
+ Sparkline = ({
3665
+ data,
3666
+ color = "auto",
3667
+ width = 80,
3668
+ height = 32,
3669
+ strokeWidth = 2,
3670
+ fill = false,
3671
+ className
3672
+ }) => {
3673
+ if (data.length < 2) return null;
3674
+ const pad = 2;
3675
+ const min = Math.min(...data);
3676
+ const max = Math.max(...data);
3677
+ const range = max - min || 1;
3678
+ const points = data.map((v, i) => {
3679
+ const x = pad + i / (data.length - 1) * (width - pad * 2);
3680
+ const y = pad + (1 - (v - min) / range) * (height - pad * 2);
3681
+ return `${x},${y}`;
3682
+ }).join(" ");
3683
+ const resolvedColor = color === "auto" ? data[data.length - 1] >= data[0] ? COLOR_VAR.success : COLOR_VAR.error : COLOR_VAR[color];
3684
+ const areaPath = fill ? `M ${pad},${height - pad} L ${points.split(" ").join(" L ")} L ${width - pad},${height - pad} Z` : null;
3685
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3686
+ "svg",
3687
+ {
3688
+ width,
3689
+ height,
3690
+ viewBox: `0 0 ${width} ${height}`,
3691
+ className: cn("flex-shrink-0", className),
3692
+ "aria-hidden": "true",
3693
+ children: [
3694
+ areaPath && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: resolvedColor, opacity: 0.15 }),
3695
+ /* @__PURE__ */ jsxRuntime.jsx(
3696
+ "polyline",
3697
+ {
3698
+ fill: "none",
3699
+ stroke: resolvedColor,
3700
+ strokeWidth,
3701
+ strokeLinecap: "round",
3702
+ strokeLinejoin: "round",
3703
+ points
3704
+ }
3705
+ )
3706
+ ]
3707
+ }
3708
+ );
3709
+ };
3710
+ Sparkline.displayName = "Sparkline";
3711
+ }
3712
+ });
3652
3713
  var Switch;
3653
3714
  var init_Switch = __esm({
3654
3715
  "components/atoms/Switch.tsx"() {
@@ -9322,7 +9383,7 @@ var init_MapView = __esm({
9322
9383
  shadowSize: [41, 41]
9323
9384
  });
9324
9385
  L.Marker.prototype.options.icon = defaultIcon;
9325
- const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback110, useState: useState95 } = React81__namespace.default;
9386
+ const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback112, useState: useState96 } = React81__namespace.default;
9326
9387
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
9327
9388
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
9328
9389
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -9367,8 +9428,8 @@ var init_MapView = __esm({
9367
9428
  showAttribution = true
9368
9429
  }) {
9369
9430
  const eventBus = useEventBus2();
9370
- const [clickedPosition, setClickedPosition] = useState95(null);
9371
- const handleMapClick = useCallback110((lat, lng) => {
9431
+ const [clickedPosition, setClickedPosition] = useState96(null);
9432
+ const handleMapClick = useCallback112((lat, lng) => {
9372
9433
  if (showClickedPin) {
9373
9434
  setClickedPosition({ lat, lng });
9374
9435
  }
@@ -9377,7 +9438,7 @@ var init_MapView = __esm({
9377
9438
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
9378
9439
  }
9379
9440
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
9380
- const handleMarkerClick = useCallback110((marker) => {
9441
+ const handleMarkerClick = useCallback112((marker) => {
9381
9442
  onMarkerClick?.(marker);
9382
9443
  if (markerClickEvent) {
9383
9444
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -19277,7 +19338,7 @@ var init_CastleTemplate = __esm({
19277
19338
  CastleTemplate.displayName = "CastleTemplate";
19278
19339
  }
19279
19340
  });
19280
- var CHART_COLORS, BarChart, PieChart, LineChart, Chart;
19341
+ var CHART_COLORS, seriesColor, monthFormatter, formatTimeLabel, BarChart, PieChart, LineChart, ScatterChart, Chart;
19281
19342
  var init_Chart = __esm({
19282
19343
  "components/organisms/Chart.tsx"() {
19283
19344
  "use client";
@@ -19297,38 +19358,159 @@ var init_Chart = __esm({
19297
19358
  "var(--color-info)",
19298
19359
  "var(--color-accent)"
19299
19360
  ];
19300
- BarChart = ({ data, height, showValues }) => {
19301
- const maxValue = Math.max(...data.map((d) => d.value), 1);
19302
- return /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", align: "end", className: "w-full", style: { height }, children: data.map((point, idx) => {
19303
- const barHeight = point.value / maxValue * 100;
19304
- const color = point.color || CHART_COLORS[idx % CHART_COLORS.length];
19305
- return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "center", flex: true, className: "min-w-0", children: [
19306
- showValues && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "tabular-nums", children: point.value }),
19307
- /* @__PURE__ */ jsxRuntime.jsx(
19308
- Box,
19309
- {
19310
- className: cn(
19311
- "w-full rounded-t-sm transition-all duration-500 ease-out min-h-[4px]"
19312
- ),
19313
- style: {
19314
- height: `${barHeight}%`,
19315
- backgroundColor: color
19316
- }
19361
+ seriesColor = (series, idx) => series.color ?? CHART_COLORS[idx % CHART_COLORS.length];
19362
+ monthFormatter = new Intl.DateTimeFormat(void 0, {
19363
+ month: "short",
19364
+ year: "2-digit"
19365
+ });
19366
+ formatTimeLabel = (raw) => {
19367
+ const parsed = new Date(raw);
19368
+ if (Number.isNaN(parsed.getTime())) return raw;
19369
+ return monthFormatter.format(parsed);
19370
+ };
19371
+ BarChart = ({ series, height, showValues, stack, timeAxis, histogram = false, onPointClick }) => {
19372
+ const categories = React81.useMemo(() => {
19373
+ const set = [];
19374
+ const seen = /* @__PURE__ */ new Set();
19375
+ for (const s of series) {
19376
+ for (const p2 of s.data) {
19377
+ if (!seen.has(p2.label)) {
19378
+ seen.add(p2.label);
19379
+ set.push(p2.label);
19317
19380
  }
19318
- ),
19319
- /* @__PURE__ */ jsxRuntime.jsx(
19320
- Typography,
19321
- {
19322
- variant: "caption",
19323
- color: "secondary",
19324
- className: "truncate w-full text-center",
19325
- children: point.label
19381
+ }
19382
+ }
19383
+ return set;
19384
+ }, [series]);
19385
+ const valueAt = React81.useCallback(
19386
+ (s, label) => {
19387
+ const p2 = s.data.find((d) => d.label === label);
19388
+ return p2 ? p2.value : 0;
19389
+ },
19390
+ []
19391
+ );
19392
+ const columnTotals = React81.useMemo(() => {
19393
+ if (stack === "none") return null;
19394
+ return categories.map(
19395
+ (label) => series.reduce((sum, s) => sum + valueAt(s, label), 0)
19396
+ );
19397
+ }, [categories, series, stack, valueAt]);
19398
+ const maxValue = React81.useMemo(() => {
19399
+ if (stack === "normalize") return 100;
19400
+ if (stack === "stack" && columnTotals) {
19401
+ return Math.max(...columnTotals, 1);
19402
+ }
19403
+ let m = 1;
19404
+ for (const s of series) {
19405
+ for (const p2 of s.data) if (p2.value > m) m = p2.value;
19406
+ }
19407
+ return m;
19408
+ }, [series, stack, columnTotals]);
19409
+ return /* @__PURE__ */ jsxRuntime.jsx(
19410
+ HStack,
19411
+ {
19412
+ gap: histogram ? "none" : "xs",
19413
+ align: "end",
19414
+ className: "w-full",
19415
+ style: { height },
19416
+ children: categories.map((label, catIdx) => {
19417
+ const displayLabel = timeAxis ? formatTimeLabel(label) : label;
19418
+ if (stack === "none") {
19419
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19420
+ VStack,
19421
+ {
19422
+ gap: "xs",
19423
+ align: "center",
19424
+ flex: true,
19425
+ className: "min-w-0",
19426
+ children: [
19427
+ /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: histogram ? "none" : "xs", align: "end", className: "w-full", style: { height: "100%" }, children: series.map((s, sIdx) => {
19428
+ const value = valueAt(s, label);
19429
+ const barHeight = value / maxValue * 100;
19430
+ const color = seriesColor(s, sIdx);
19431
+ return /* @__PURE__ */ jsxRuntime.jsx(
19432
+ Box,
19433
+ {
19434
+ className: cn(
19435
+ "rounded-t-sm transition-all duration-500 ease-out min-h-[4px] cursor-pointer hover:opacity-80",
19436
+ histogram ? "flex-1 mx-0" : "flex-1"
19437
+ ),
19438
+ style: {
19439
+ height: `${barHeight}%`,
19440
+ backgroundColor: color
19441
+ },
19442
+ onClick: () => onPointClick?.(
19443
+ { label, value, color },
19444
+ s.name
19445
+ ),
19446
+ title: `${s.name}: ${value}`
19447
+ },
19448
+ s.name
19449
+ );
19450
+ }) }),
19451
+ showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "tabular-nums", children: valueAt(series[0], label) }),
19452
+ /* @__PURE__ */ jsxRuntime.jsx(
19453
+ Typography,
19454
+ {
19455
+ variant: "caption",
19456
+ color: "secondary",
19457
+ className: "truncate w-full text-center",
19458
+ children: displayLabel
19459
+ }
19460
+ )
19461
+ ]
19462
+ },
19463
+ label
19464
+ );
19326
19465
  }
19327
- )
19328
- ] }, point.label);
19329
- }) });
19466
+ const total = columnTotals?.[catIdx] ?? 1;
19467
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19468
+ VStack,
19469
+ {
19470
+ gap: "xs",
19471
+ align: "center",
19472
+ flex: true,
19473
+ className: "min-w-0",
19474
+ children: [
19475
+ /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "none", className: "w-full", style: { height: "100%" }, justify: "end", children: series.map((s, sIdx) => {
19476
+ const value = valueAt(s, label);
19477
+ const ratio = stack === "normalize" ? total === 0 ? 0 : value / total * 100 : value / maxValue * 100;
19478
+ const color = seriesColor(s, sIdx);
19479
+ return /* @__PURE__ */ jsxRuntime.jsx(
19480
+ Box,
19481
+ {
19482
+ className: "w-full transition-all duration-500 ease-out cursor-pointer hover:opacity-80",
19483
+ style: {
19484
+ height: `${ratio}%`,
19485
+ backgroundColor: color
19486
+ },
19487
+ onClick: () => onPointClick?.(
19488
+ { label, value, color },
19489
+ s.name
19490
+ ),
19491
+ title: `${s.name}: ${value}`
19492
+ },
19493
+ s.name
19494
+ );
19495
+ }) }),
19496
+ /* @__PURE__ */ jsxRuntime.jsx(
19497
+ Typography,
19498
+ {
19499
+ variant: "caption",
19500
+ color: "secondary",
19501
+ className: "truncate w-full text-center",
19502
+ children: displayLabel
19503
+ }
19504
+ )
19505
+ ]
19506
+ },
19507
+ label
19508
+ );
19509
+ })
19510
+ }
19511
+ );
19330
19512
  };
19331
- PieChart = ({ data, height, showValues, donut = false }) => {
19513
+ PieChart = ({ data, height, showValues, donut = false, onPointClick }) => {
19332
19514
  const total = data.reduce((sum, d) => sum + d.value, 0);
19333
19515
  const size = Math.min(height, 200);
19334
19516
  const radius = size / 2 - 8;
@@ -19374,7 +19556,11 @@ var init_Chart = __esm({
19374
19556
  fill: seg.color,
19375
19557
  stroke: "var(--color-card)",
19376
19558
  strokeWidth: "2",
19377
- className: "transition-opacity duration-200 hover:opacity-80"
19559
+ className: "transition-opacity duration-200 hover:opacity-80 cursor-pointer",
19560
+ onClick: () => onPointClick?.(
19561
+ { label: seg.label, value: seg.value, color: seg.color },
19562
+ "default"
19563
+ )
19378
19564
  },
19379
19565
  idx
19380
19566
  )),
@@ -19409,56 +19595,243 @@ var init_Chart = __esm({
19409
19595
  ] }, idx)) })
19410
19596
  ] });
19411
19597
  };
19412
- LineChart = ({ data, height, showValues, fill = false }) => {
19413
- const maxValue = Math.max(...data.map((d) => d.value), 1);
19598
+ LineChart = ({ series, height, showValues, fill = false, timeAxis, onPointClick }) => {
19414
19599
  const width = 400;
19415
19600
  const padding = { top: 20, right: 20, bottom: 30, left: 40 };
19416
19601
  const chartWidth = width - padding.left - padding.right;
19417
19602
  const chartHeight = height - padding.top - padding.bottom;
19418
- const points = React81.useMemo(() => {
19419
- return data.map((point, idx) => ({
19420
- x: padding.left + idx / Math.max(data.length - 1, 1) * chartWidth,
19421
- y: padding.top + chartHeight - point.value / maxValue * chartHeight,
19422
- ...point
19423
- }));
19424
- }, [data, maxValue, chartWidth, chartHeight, padding]);
19425
- const linePath = points.map((p2, i) => `${i === 0 ? "M" : "L"} ${p2.x} ${p2.y}`).join(" ");
19426
- const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
19427
- return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "100%", height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "xMidYMid meet", children: [
19428
- [0, 0.25, 0.5, 0.75, 1].map((frac) => {
19429
- const y = padding.top + chartHeight * (1 - frac);
19430
- return /* @__PURE__ */ jsxRuntime.jsx(
19431
- "line",
19432
- {
19433
- x1: padding.left,
19434
- y1: y,
19435
- x2: width - padding.right,
19436
- y2: y,
19437
- stroke: "var(--color-border)",
19438
- strokeDasharray: "4 4",
19439
- opacity: 0.5
19440
- },
19441
- frac
19442
- );
19443
- }),
19444
- fill && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: "var(--color-primary)", opacity: 0.1 }),
19445
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: linePath, fill: "none", stroke: "var(--color-primary)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
19446
- points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19447
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: p2.x, cy: p2.y, r: "4", fill: "var(--color-card)", stroke: "var(--color-primary)", strokeWidth: "2" }),
19448
- showValues && /* @__PURE__ */ jsxRuntime.jsx("text", { x: p2.x, y: p2.y - 10, textAnchor: "middle", fill: "var(--color-foreground)", fontSize: "10", fontWeight: "500", children: p2.value }),
19449
- /* @__PURE__ */ jsxRuntime.jsx(
19450
- "text",
19451
- {
19452
- x: p2.x,
19453
- y: height - 8,
19454
- textAnchor: "middle",
19455
- fill: "var(--color-muted-foreground)",
19456
- fontSize: "9",
19457
- children: p2.label
19603
+ const labels = React81.useMemo(() => {
19604
+ const seen = /* @__PURE__ */ new Set();
19605
+ const out = [];
19606
+ for (const s of series) {
19607
+ for (const p2 of s.data) {
19608
+ if (!seen.has(p2.label)) {
19609
+ seen.add(p2.label);
19610
+ out.push(p2.label);
19458
19611
  }
19459
- )
19460
- ] }, idx))
19461
- ] });
19612
+ }
19613
+ }
19614
+ return out;
19615
+ }, [series]);
19616
+ const maxValue = React81.useMemo(() => {
19617
+ let m = 1;
19618
+ for (const s of series) {
19619
+ for (const p2 of s.data) if (p2.value > m) m = p2.value;
19620
+ }
19621
+ return m;
19622
+ }, [series]);
19623
+ const xFor = React81.useCallback(
19624
+ (idx) => padding.left + idx / Math.max(labels.length - 1, 1) * chartWidth,
19625
+ [labels.length, chartWidth, padding.left]
19626
+ );
19627
+ const yFor = React81.useCallback(
19628
+ (value) => padding.top + chartHeight - value / maxValue * chartHeight,
19629
+ [maxValue, chartHeight, padding.top]
19630
+ );
19631
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19632
+ "svg",
19633
+ {
19634
+ width: "100%",
19635
+ height,
19636
+ viewBox: `0 0 ${width} ${height}`,
19637
+ preserveAspectRatio: "xMidYMid meet",
19638
+ children: [
19639
+ [0, 0.25, 0.5, 0.75, 1].map((frac) => {
19640
+ const y = padding.top + chartHeight * (1 - frac);
19641
+ return /* @__PURE__ */ jsxRuntime.jsx(
19642
+ "line",
19643
+ {
19644
+ x1: padding.left,
19645
+ y1: y,
19646
+ x2: width - padding.right,
19647
+ y2: y,
19648
+ stroke: "var(--color-border)",
19649
+ strokeDasharray: "4 4",
19650
+ opacity: 0.5
19651
+ },
19652
+ frac
19653
+ );
19654
+ }),
19655
+ series.map((s, sIdx) => {
19656
+ const color = seriesColor(s, sIdx);
19657
+ const points = labels.map((label, idx) => {
19658
+ const point = s.data.find((d) => d.label === label);
19659
+ return {
19660
+ x: xFor(idx),
19661
+ y: yFor(point ? point.value : 0),
19662
+ value: point ? point.value : 0,
19663
+ label
19664
+ };
19665
+ });
19666
+ const linePath = points.map((p2, i) => `${i === 0 ? "M" : "L"} ${p2.x} ${p2.y}`).join(" ");
19667
+ const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
19668
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19669
+ fill && /* @__PURE__ */ jsxRuntime.jsx(
19670
+ "path",
19671
+ {
19672
+ d: areaPath,
19673
+ fill: color,
19674
+ opacity: series.length > 1 ? 0.08 : 0.1
19675
+ }
19676
+ ),
19677
+ /* @__PURE__ */ jsxRuntime.jsx(
19678
+ "path",
19679
+ {
19680
+ d: linePath,
19681
+ fill: "none",
19682
+ stroke: color,
19683
+ strokeWidth: "2",
19684
+ strokeLinecap: "round",
19685
+ strokeLinejoin: "round",
19686
+ strokeDasharray: s.dashed ? "6 4" : void 0
19687
+ }
19688
+ ),
19689
+ points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19690
+ /* @__PURE__ */ jsxRuntime.jsx(
19691
+ "circle",
19692
+ {
19693
+ cx: p2.x,
19694
+ cy: p2.y,
19695
+ r: "4",
19696
+ fill: "var(--color-card)",
19697
+ stroke: color,
19698
+ strokeWidth: "2",
19699
+ className: "cursor-pointer",
19700
+ onClick: () => onPointClick?.(
19701
+ { label: p2.label, value: p2.value, color },
19702
+ s.name
19703
+ )
19704
+ }
19705
+ ),
19706
+ showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(
19707
+ "text",
19708
+ {
19709
+ x: p2.x,
19710
+ y: p2.y - 10,
19711
+ textAnchor: "middle",
19712
+ fill: "var(--color-foreground)",
19713
+ fontSize: "10",
19714
+ fontWeight: "500",
19715
+ children: p2.value
19716
+ }
19717
+ )
19718
+ ] }, idx))
19719
+ ] }, s.name);
19720
+ }),
19721
+ labels.map((label, idx) => /* @__PURE__ */ jsxRuntime.jsx(
19722
+ "text",
19723
+ {
19724
+ x: xFor(idx),
19725
+ y: height - 8,
19726
+ textAnchor: "middle",
19727
+ fill: "var(--color-muted-foreground)",
19728
+ fontSize: "9",
19729
+ children: timeAxis ? formatTimeLabel(label) : label
19730
+ },
19731
+ label
19732
+ ))
19733
+ ]
19734
+ }
19735
+ );
19736
+ };
19737
+ ScatterChart = ({ data, height, onPointClick }) => {
19738
+ const width = 400;
19739
+ const padding = { top: 20, right: 20, bottom: 30, left: 40 };
19740
+ const chartWidth = width - padding.left - padding.right;
19741
+ const chartHeight = height - padding.top - padding.bottom;
19742
+ const { minX, maxX, minY, maxY } = React81.useMemo(() => {
19743
+ if (data.length === 0) {
19744
+ return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
19745
+ }
19746
+ let mnX = data[0].x;
19747
+ let mxX = data[0].x;
19748
+ let mnY = data[0].y;
19749
+ let mxY = data[0].y;
19750
+ for (const p2 of data) {
19751
+ if (p2.x < mnX) mnX = p2.x;
19752
+ if (p2.x > mxX) mxX = p2.x;
19753
+ if (p2.y < mnY) mnY = p2.y;
19754
+ if (p2.y > mxY) mxY = p2.y;
19755
+ }
19756
+ return { minX: mnX, maxX: mxX, minY: mnY, maxY: mxY };
19757
+ }, [data]);
19758
+ const rangeX = maxX - minX || 1;
19759
+ const rangeY = maxY - minY || 1;
19760
+ return /* @__PURE__ */ jsxRuntime.jsxs(
19761
+ "svg",
19762
+ {
19763
+ width: "100%",
19764
+ height,
19765
+ viewBox: `0 0 ${width} ${height}`,
19766
+ preserveAspectRatio: "xMidYMid meet",
19767
+ children: [
19768
+ [0, 0.25, 0.5, 0.75, 1].map((frac) => {
19769
+ const y = padding.top + chartHeight * (1 - frac);
19770
+ return /* @__PURE__ */ jsxRuntime.jsx(
19771
+ "line",
19772
+ {
19773
+ x1: padding.left,
19774
+ y1: y,
19775
+ x2: width - padding.right,
19776
+ y2: y,
19777
+ stroke: "var(--color-border)",
19778
+ strokeDasharray: "4 4",
19779
+ opacity: 0.5
19780
+ },
19781
+ frac
19782
+ );
19783
+ }),
19784
+ data.map((p2, idx) => {
19785
+ const cx = padding.left + (p2.x - minX) / rangeX * chartWidth;
19786
+ const cy = padding.top + chartHeight - (p2.y - minY) / rangeY * chartHeight;
19787
+ const r = p2.size ?? 5;
19788
+ const color = p2.color ?? CHART_COLORS[idx % CHART_COLORS.length];
19789
+ return /* @__PURE__ */ jsxRuntime.jsx(
19790
+ "circle",
19791
+ {
19792
+ cx,
19793
+ cy,
19794
+ r,
19795
+ fill: color,
19796
+ opacity: 0.7,
19797
+ className: "cursor-pointer hover:opacity-100",
19798
+ onClick: () => onPointClick?.(
19799
+ {
19800
+ label: p2.label ?? `(${p2.x}, ${p2.y})`,
19801
+ value: p2.y,
19802
+ color
19803
+ },
19804
+ "default"
19805
+ ),
19806
+ children: /* @__PURE__ */ jsxRuntime.jsx("title", { children: p2.label ?? `(${p2.x}, ${p2.y})` })
19807
+ },
19808
+ idx
19809
+ );
19810
+ }),
19811
+ /* @__PURE__ */ jsxRuntime.jsx(
19812
+ "text",
19813
+ {
19814
+ x: padding.left,
19815
+ y: height - 8,
19816
+ fill: "var(--color-muted-foreground)",
19817
+ fontSize: "9",
19818
+ children: minX.toFixed(1)
19819
+ }
19820
+ ),
19821
+ /* @__PURE__ */ jsxRuntime.jsx(
19822
+ "text",
19823
+ {
19824
+ x: width - padding.right,
19825
+ y: height - 8,
19826
+ textAnchor: "end",
19827
+ fill: "var(--color-muted-foreground)",
19828
+ fontSize: "9",
19829
+ children: maxX.toFixed(1)
19830
+ }
19831
+ )
19832
+ ]
19833
+ }
19834
+ );
19462
19835
  };
19463
19836
  Chart = ({
19464
19837
  title,
@@ -19466,9 +19839,13 @@ var init_Chart = __esm({
19466
19839
  chartType = "bar",
19467
19840
  series,
19468
19841
  data: simpleData,
19842
+ scatterData,
19469
19843
  height = 200,
19470
19844
  showLegend = true,
19471
19845
  showValues = false,
19846
+ stack = "none",
19847
+ timeAxis = false,
19848
+ drillEvent,
19472
19849
  actions,
19473
19850
  entity,
19474
19851
  isLoading = false,
@@ -19485,11 +19862,25 @@ var init_Chart = __esm({
19485
19862
  },
19486
19863
  [eventBus]
19487
19864
  );
19488
- const normalizedData = React81.useMemo(() => {
19489
- if (simpleData) return simpleData;
19490
- if (series && series.length > 0) return series[0].data;
19865
+ const handlePointClick = React81.useCallback(
19866
+ (point, seriesName) => {
19867
+ if (drillEvent) {
19868
+ eventBus.emit(`UI:${drillEvent}`, {
19869
+ label: point.label,
19870
+ value: point.value,
19871
+ seriesLabel: seriesName === "default" ? void 0 : seriesName
19872
+ });
19873
+ }
19874
+ },
19875
+ [drillEvent, eventBus]
19876
+ );
19877
+ const normalizedSeries = React81.useMemo(() => {
19878
+ if (series && series.length > 0) return series;
19879
+ if (simpleData) return [{ name: "default", data: simpleData }];
19491
19880
  return [];
19492
19881
  }, [simpleData, series]);
19882
+ const firstSeriesData = normalizedSeries[0]?.data ?? [];
19883
+ const hasContent = chartType === "scatter" ? (scatterData?.length ?? 0) > 0 : normalizedSeries.some((s) => s.data.length > 0);
19493
19884
  if (isLoading) {
19494
19885
  return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: "Loading chart...", className });
19495
19886
  }
@@ -19503,7 +19894,7 @@ var init_Chart = __esm({
19503
19894
  }
19504
19895
  );
19505
19896
  }
19506
- if (normalizedData.length === 0) {
19897
+ if (!hasContent) {
19507
19898
  return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { title: t("empty.noData"), description: t("empty.noData"), className });
19508
19899
  }
19509
19900
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn("p-6", className), children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", children: [
@@ -19524,18 +19915,84 @@ var init_Chart = __esm({
19524
19915
  )) })
19525
19916
  ] }),
19526
19917
  /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "w-full", children: [
19527
- chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(BarChart, { data: normalizedData, height, showValues }),
19528
- chartType === "line" && /* @__PURE__ */ jsxRuntime.jsx(LineChart, { data: normalizedData, height, showValues }),
19529
- chartType === "area" && /* @__PURE__ */ jsxRuntime.jsx(LineChart, { data: normalizedData, height, showValues, fill: true }),
19530
- chartType === "pie" && /* @__PURE__ */ jsxRuntime.jsx(PieChart, { data: normalizedData, height, showValues: showLegend }),
19531
- chartType === "donut" && /* @__PURE__ */ jsxRuntime.jsx(PieChart, { data: normalizedData, height, showValues: showLegend, donut: true })
19918
+ chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(
19919
+ BarChart,
19920
+ {
19921
+ series: normalizedSeries,
19922
+ height,
19923
+ showValues,
19924
+ stack,
19925
+ timeAxis,
19926
+ onPointClick: handlePointClick
19927
+ }
19928
+ ),
19929
+ chartType === "histogram" && /* @__PURE__ */ jsxRuntime.jsx(
19930
+ BarChart,
19931
+ {
19932
+ series: normalizedSeries,
19933
+ height,
19934
+ showValues,
19935
+ stack: "none",
19936
+ timeAxis: false,
19937
+ histogram: true,
19938
+ onPointClick: handlePointClick
19939
+ }
19940
+ ),
19941
+ chartType === "line" && /* @__PURE__ */ jsxRuntime.jsx(
19942
+ LineChart,
19943
+ {
19944
+ series: normalizedSeries,
19945
+ height,
19946
+ showValues,
19947
+ timeAxis,
19948
+ onPointClick: handlePointClick
19949
+ }
19950
+ ),
19951
+ chartType === "area" && /* @__PURE__ */ jsxRuntime.jsx(
19952
+ LineChart,
19953
+ {
19954
+ series: normalizedSeries,
19955
+ height,
19956
+ showValues,
19957
+ timeAxis,
19958
+ fill: true,
19959
+ onPointClick: handlePointClick
19960
+ }
19961
+ ),
19962
+ chartType === "pie" && /* @__PURE__ */ jsxRuntime.jsx(
19963
+ PieChart,
19964
+ {
19965
+ data: firstSeriesData,
19966
+ height,
19967
+ showValues: showLegend,
19968
+ onPointClick: handlePointClick
19969
+ }
19970
+ ),
19971
+ chartType === "donut" && /* @__PURE__ */ jsxRuntime.jsx(
19972
+ PieChart,
19973
+ {
19974
+ data: firstSeriesData,
19975
+ height,
19976
+ showValues: showLegend,
19977
+ donut: true,
19978
+ onPointClick: handlePointClick
19979
+ }
19980
+ ),
19981
+ chartType === "scatter" && /* @__PURE__ */ jsxRuntime.jsx(
19982
+ ScatterChart,
19983
+ {
19984
+ data: scatterData ?? [],
19985
+ height,
19986
+ onPointClick: handlePointClick
19987
+ }
19988
+ )
19532
19989
  ] }),
19533
- showLegend && series && series.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "md", justify: "center", wrap: true, children: series.map((s, idx) => /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
19990
+ showLegend && normalizedSeries.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "md", justify: "center", wrap: true, children: normalizedSeries.map((s, idx) => /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
19534
19991
  /* @__PURE__ */ jsxRuntime.jsx(
19535
19992
  Box,
19536
19993
  {
19537
19994
  className: "w-3 h-3 rounded-full flex-shrink-0",
19538
- style: { backgroundColor: s.color || CHART_COLORS[idx % CHART_COLORS.length] }
19995
+ style: { backgroundColor: seriesColor(s, idx) }
19539
19996
  }
19540
19997
  ),
19541
19998
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: s.name })
@@ -24451,6 +24908,151 @@ var init_FlipCard = __esm({
24451
24908
  FlipCard.displayName = "FlipCard";
24452
24909
  }
24453
24910
  });
24911
+ function toISODate(d) {
24912
+ return d.toISOString().slice(0, 10);
24913
+ }
24914
+ function startOfMonth(d) {
24915
+ return new Date(d.getFullYear(), d.getMonth(), 1);
24916
+ }
24917
+ function startOfQuarter(d) {
24918
+ return new Date(d.getFullYear(), Math.floor(d.getMonth() / 3) * 3, 1);
24919
+ }
24920
+ function startOfYear(d) {
24921
+ return new Date(d.getFullYear(), 0, 1);
24922
+ }
24923
+ function daysAgo(n) {
24924
+ const d = /* @__PURE__ */ new Date();
24925
+ d.setDate(d.getDate() - n);
24926
+ return d;
24927
+ }
24928
+ var DEFAULT_PRESETS, DateRangePicker;
24929
+ var init_DateRangePicker = __esm({
24930
+ "components/molecules/DateRangePicker.tsx"() {
24931
+ "use client";
24932
+ init_cn();
24933
+ init_Button();
24934
+ init_Input();
24935
+ init_Stack();
24936
+ init_Typography();
24937
+ init_useEventBus();
24938
+ DEFAULT_PRESETS = [
24939
+ {
24940
+ label: "Last 7 days",
24941
+ value: "7d",
24942
+ range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
24943
+ },
24944
+ {
24945
+ label: "Last 30 days",
24946
+ value: "30d",
24947
+ range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
24948
+ },
24949
+ {
24950
+ label: "This Month",
24951
+ value: "month",
24952
+ range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
24953
+ },
24954
+ {
24955
+ label: "This Quarter",
24956
+ value: "quarter",
24957
+ range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
24958
+ },
24959
+ {
24960
+ label: "YTD",
24961
+ value: "ytd",
24962
+ range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
24963
+ }
24964
+ ];
24965
+ DateRangePicker = ({
24966
+ from: fromProp,
24967
+ to: toProp,
24968
+ event,
24969
+ onChange,
24970
+ presets = DEFAULT_PRESETS,
24971
+ fromLabel = "From",
24972
+ toLabel = "To",
24973
+ className
24974
+ }) => {
24975
+ const eventBus = useEventBus();
24976
+ const [from, setFrom] = React81.useState(fromProp ?? "");
24977
+ const [to, setTo] = React81.useState(toProp ?? "");
24978
+ const [activePreset, setActivePreset] = React81.useState(null);
24979
+ const emit = React81.useCallback(
24980
+ (range) => {
24981
+ onChange?.(range);
24982
+ if (event) eventBus.emit(`UI:${event}`, range);
24983
+ },
24984
+ [onChange, event, eventBus]
24985
+ );
24986
+ const handleFromChange = React81.useCallback(
24987
+ (next) => {
24988
+ setFrom(next);
24989
+ setActivePreset(null);
24990
+ emit({ from: next, to });
24991
+ },
24992
+ [to, emit]
24993
+ );
24994
+ const handleToChange = React81.useCallback(
24995
+ (next) => {
24996
+ setTo(next);
24997
+ setActivePreset(null);
24998
+ emit({ from, to: next });
24999
+ },
25000
+ [from, emit]
25001
+ );
25002
+ const handlePreset = React81.useCallback(
25003
+ (preset) => {
25004
+ const range = preset.range();
25005
+ setFrom(range.from);
25006
+ setTo(range.to);
25007
+ setActivePreset(preset.value);
25008
+ emit(range);
25009
+ },
25010
+ [emit]
25011
+ );
25012
+ const presetButtons = React81.useMemo(
25013
+ () => presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
25014
+ Button,
25015
+ {
25016
+ variant: activePreset === preset.value ? "primary" : "ghost",
25017
+ size: "sm",
25018
+ onClick: () => handlePreset(preset),
25019
+ children: preset.label
25020
+ },
25021
+ preset.value
25022
+ )),
25023
+ [presets, activePreset, handlePreset]
25024
+ );
25025
+ return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: cn(className), children: [
25026
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", align: "end", children: [
25027
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
25028
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: fromLabel }),
25029
+ /* @__PURE__ */ jsxRuntime.jsx(
25030
+ Input,
25031
+ {
25032
+ type: "date",
25033
+ value: from,
25034
+ onChange: (e) => handleFromChange(e.target.value)
25035
+ }
25036
+ )
25037
+ ] }),
25038
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
25039
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: toLabel }),
25040
+ /* @__PURE__ */ jsxRuntime.jsx(
25041
+ Input,
25042
+ {
25043
+ type: "date",
25044
+ value: to,
25045
+ onChange: (e) => handleToChange(e.target.value)
25046
+ }
25047
+ )
25048
+ ] })
25049
+ ] }),
25050
+ presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
25051
+ ] });
25052
+ };
25053
+ DateRangePicker.displayName = "DateRangePicker";
25054
+ }
25055
+ });
24454
25056
  var DEFAULT_OPTIONS, DateRangeSelector;
24455
25057
  var init_DateRangeSelector = __esm({
24456
25058
  "components/molecules/DateRangeSelector.tsx"() {
@@ -27422,7 +28024,9 @@ var init_StatDisplay = __esm({
27422
28024
  init_Typography();
27423
28025
  init_Box();
27424
28026
  init_Stack();
28027
+ init_Sparkline();
27425
28028
  init_Icon();
28029
+ init_useEventBus();
27426
28030
  variantColor = {
27427
28031
  default: "text-foreground",
27428
28032
  primary: "text-primary",
@@ -27437,6 +28041,10 @@ var init_StatDisplay = __esm({
27437
28041
  max,
27438
28042
  target,
27439
28043
  trend,
28044
+ trendPolarity = "higher-is-better",
28045
+ trendFormat = "absolute",
28046
+ sparklineData,
28047
+ clickEvent,
27440
28048
  prefix,
27441
28049
  suffix,
27442
28050
  icon: iconProp,
@@ -27450,6 +28058,10 @@ var init_StatDisplay = __esm({
27450
28058
  isLoading = false,
27451
28059
  error = null
27452
28060
  }) => {
28061
+ const eventBus = useEventBus();
28062
+ const handleClick = React81.useCallback(() => {
28063
+ if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { metricLabel: label });
28064
+ }, [clickEvent, eventBus, label]);
27453
28065
  const ResolvedIcon = typeof iconProp === "string" ? resolveIcon(iconProp) : null;
27454
28066
  const iconSizes3 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
27455
28067
  const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
@@ -27460,7 +28072,10 @@ var init_StatDisplay = __esm({
27460
28072
  const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
27461
28073
  const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
27462
28074
  const trendUp = showTrend && trend > 0;
27463
- const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${Math.abs(trend)}` : "";
28075
+ const trendIsGood = trendPolarity === "lower-is-better" ? !trendUp : trendUp;
28076
+ const trendMagnitude = Math.abs(trend);
28077
+ const trendSuffix = trendFormat === "percent" ? "%" : "";
28078
+ const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${trendMagnitude}${trendSuffix}` : "";
27464
28079
  if (error) {
27465
28080
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "error", children: error.message }) });
27466
28081
  }
@@ -27471,38 +28086,57 @@ var init_StatDisplay = __esm({
27471
28086
  ] }) });
27472
28087
  }
27473
28088
  if (compact) {
27474
- return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: cn("items-center", className), children: [
27475
- ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
27476
- typeof iconProp !== "string" && iconProp,
27477
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
27478
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
27479
- showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendUp ? "text-success" : "text-error"), children: trendLabel })
27480
- ] });
28089
+ return /* @__PURE__ */ jsxRuntime.jsxs(
28090
+ HStack,
28091
+ {
28092
+ gap: "sm",
28093
+ className: cn("items-center", clickEvent && "cursor-pointer hover:opacity-80", className),
28094
+ onClick: clickEvent ? handleClick : void 0,
28095
+ children: [
28096
+ ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
28097
+ typeof iconProp !== "string" && iconProp,
28098
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
28099
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
28100
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendIsGood ? "text-success" : "text-error"), children: trendLabel }),
28101
+ sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto", width: 60, height: 20 })
28102
+ ]
28103
+ }
28104
+ );
27481
28105
  }
27482
- return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
27483
- /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
27484
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
27485
- /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
27486
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
27487
- showTrend && /* @__PURE__ */ jsxRuntime.jsx(
27488
- Typography,
27489
- {
27490
- variant: "caption",
27491
- className: cn("font-semibold pb-1", trendUp ? "text-success" : "text-error"),
27492
- children: trendLabel
27493
- }
27494
- )
27495
- ] }),
27496
- showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
27497
- Box,
27498
- {
27499
- className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
27500
- style: { width: `${targetPct}%` }
27501
- }
27502
- ) })
27503
- ] }),
27504
- (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }) : iconProp })
27505
- ] }) });
28106
+ return /* @__PURE__ */ jsxRuntime.jsx(
28107
+ Card,
28108
+ {
28109
+ className: cn(padSizes[size], clickEvent && "cursor-pointer hover:shadow-md transition-shadow", className),
28110
+ onClick: clickEvent ? handleClick : void 0,
28111
+ children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
28112
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
28113
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
28114
+ /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
28115
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
28116
+ showTrend && /* @__PURE__ */ jsxRuntime.jsx(
28117
+ Typography,
28118
+ {
28119
+ variant: "caption",
28120
+ className: cn("font-semibold pb-1", trendIsGood ? "text-success" : "text-error"),
28121
+ children: trendLabel
28122
+ }
28123
+ )
28124
+ ] }),
28125
+ showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
28126
+ Box,
28127
+ {
28128
+ className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
28129
+ style: { width: `${targetPct}%` }
28130
+ }
28131
+ ) })
28132
+ ] }),
28133
+ /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
28134
+ (ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }) : iconProp }),
28135
+ sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
28136
+ ] })
28137
+ ] })
28138
+ }
28139
+ );
27506
28140
  };
27507
28141
  StatDisplay.displayName = "StatDisplay";
27508
28142
  }
@@ -41965,6 +42599,7 @@ var init_StatCard = __esm({
41965
42599
  init_Box();
41966
42600
  init_Stack();
41967
42601
  init_Button();
42602
+ init_Sparkline();
41968
42603
  init_useEventBus();
41969
42604
  init_useTranslate();
41970
42605
  init_Icon();
@@ -42134,32 +42769,7 @@ var init_StatCard = __esm({
42134
42769
  ] }),
42135
42770
  /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
42136
42771
  Icon3 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3", iconBg), children: /* @__PURE__ */ jsxRuntime.jsx(Icon3, { className: cn("h-6 w-6", iconColor) }) }),
42137
- sparklineData && sparklineData.length > 1 && (() => {
42138
- const w = 80;
42139
- const h = 32;
42140
- const pad = 2;
42141
- const min = Math.min(...sparklineData);
42142
- const max = Math.max(...sparklineData);
42143
- const range = max - min || 1;
42144
- const points = sparklineData.map((v, i) => {
42145
- const x = pad + i / (sparklineData.length - 1) * (w - pad * 2);
42146
- const y = pad + (1 - (v - min) / range) * (h - pad * 2);
42147
- return `${x},${y}`;
42148
- }).join(" ");
42149
- const trending = sparklineData[sparklineData.length - 1] >= sparklineData[0];
42150
- const strokeColor = trending ? "var(--color-success)" : "var(--color-error)";
42151
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w, height: h, viewBox: `0 0 ${w} ${h}`, className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
42152
- "polyline",
42153
- {
42154
- fill: "none",
42155
- stroke: strokeColor,
42156
- strokeWidth: "2",
42157
- strokeLinecap: "round",
42158
- strokeLinejoin: "round",
42159
- points
42160
- }
42161
- ) });
42162
- })()
42772
+ sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
42163
42773
  ] })
42164
42774
  ] }),
42165
42775
  action && /* @__PURE__ */ jsxRuntime.jsxs(
@@ -44057,6 +44667,7 @@ var init_component_registry_generated = __esm({
44057
44667
  init_DataGrid();
44058
44668
  init_DataList();
44059
44669
  init_DataTable();
44670
+ init_DateRangePicker();
44060
44671
  init_DateRangeSelector();
44061
44672
  init_DayCell();
44062
44673
  init_DebuggerBoard();
@@ -44189,6 +44800,7 @@ var init_component_registry_generated = __esm({
44189
44800
  init_Skeleton();
44190
44801
  init_SocialProof();
44191
44802
  init_SortableList();
44803
+ init_Sparkline();
44192
44804
  init_Split();
44193
44805
  init_SplitPane();
44194
44806
  init_SplitSection();
@@ -44337,6 +44949,7 @@ var init_component_registry_generated = __esm({
44337
44949
  "DataGrid": DataGrid,
44338
44950
  "DataList": DataList,
44339
44951
  "DataTable": DataTable,
44952
+ "DateRangePicker": DateRangePicker,
44340
44953
  "DateRangeSelector": DateRangeSelector,
44341
44954
  "DayCell": DayCell,
44342
44955
  "DebuggerBoard": DebuggerBoard,
@@ -44498,6 +45111,7 @@ var init_component_registry_generated = __esm({
44498
45111
  "SortableList": SortableList,
44499
45112
  "Spacer": SpacerPattern,
44500
45113
  "SpacerPattern": SpacerPattern,
45114
+ "Sparkline": Sparkline,
44501
45115
  "Spinner": SpinnerPattern,
44502
45116
  "SpinnerPattern": SpinnerPattern,
44503
45117
  "Split": Split,