@underverse-ui/underverse 0.2.39 → 0.2.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -10274,23 +10274,1387 @@ GridItem.displayName = "Grid.Item";
10274
10274
  var Grid = Object.assign(GridRoot, { Item: GridItem });
10275
10275
  var Grid_default = Grid;
10276
10276
 
10277
- // ../../components/ui/ClientOnly.tsx
10277
+ // ../../components/ui/LineChart.tsx
10278
+ import { useMemo as useMemo6, useState as useState33, useRef as useRef14 } from "react";
10279
+
10280
+ // ../../components/ui/ChartTooltip.tsx
10278
10281
  import { useEffect as useEffect18, useState as useState32 } from "react";
10279
- import { Fragment as Fragment16, jsx as jsx45 } from "react/jsx-runtime";
10280
- function ClientOnly({ children, fallback = null }) {
10281
- const [hasMounted, setHasMounted] = useState32(false);
10282
+ import { createPortal as createPortal10 } from "react-dom";
10283
+ import { Fragment as Fragment16, jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
10284
+ function ChartTooltip({ x, y, visible, label, value, color, secondaryLabel, secondaryValue, items, containerRef }) {
10285
+ const [isMounted, setIsMounted] = useState32(false);
10286
+ const [position, setPosition] = useState32(null);
10282
10287
  useEffect18(() => {
10288
+ setIsMounted(true);
10289
+ }, []);
10290
+ useEffect18(() => {
10291
+ if (visible && containerRef?.current) {
10292
+ const rect = containerRef.current.getBoundingClientRect();
10293
+ setPosition({
10294
+ top: rect.top + y,
10295
+ left: rect.left + x
10296
+ });
10297
+ }
10298
+ }, [visible, x, y, containerRef]);
10299
+ if (!visible || !isMounted || !position) return null;
10300
+ const tooltipContent = /* @__PURE__ */ jsxs40(
10301
+ "div",
10302
+ {
10303
+ style: {
10304
+ position: "fixed",
10305
+ top: position.top,
10306
+ left: position.left + 12,
10307
+ zIndex: 99999,
10308
+ pointerEvents: "none",
10309
+ animation: "chartTooltipFadeIn 0.15s ease-out"
10310
+ },
10311
+ children: [
10312
+ /* @__PURE__ */ jsxs40(
10313
+ "div",
10314
+ {
10315
+ className: cn("bg-popover text-popover-foreground border border-border", "rounded-lg shadow-xl px-3 py-2 text-sm", "backdrop-blur-sm"),
10316
+ style: {
10317
+ minWidth: "80px",
10318
+ width: "max-content",
10319
+ boxShadow: "0 10px 25px -3px rgba(0, 0, 0, 0.5), 0 4px 10px -2px rgba(0, 0, 0, 0.3)"
10320
+ },
10321
+ children: [
10322
+ label && /* @__PURE__ */ jsx45("div", { className: "text-muted-foreground text-xs mb-1", children: label }),
10323
+ items && items.length > 0 ? /* @__PURE__ */ jsx45("div", { className: "flex flex-col gap-1", children: items.map((item, i) => /* @__PURE__ */ jsxs40("div", { className: "flex items-center gap-2", children: [
10324
+ item.color && /* @__PURE__ */ jsx45("div", { className: "w-2 h-2 rounded-full shrink-0", style: { backgroundColor: item.color } }),
10325
+ /* @__PURE__ */ jsxs40("span", { className: "text-muted-foreground", children: [
10326
+ item.label,
10327
+ ":"
10328
+ ] }),
10329
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold ml-auto", children: item.value })
10330
+ ] }, i)) }) : /* @__PURE__ */ jsxs40(Fragment16, { children: [
10331
+ /* @__PURE__ */ jsxs40("div", { className: "flex items-center gap-2", children: [
10332
+ color && /* @__PURE__ */ jsx45("div", { className: "w-2 h-2 rounded-full shrink-0", style: { backgroundColor: color } }),
10333
+ /* @__PURE__ */ jsx45("span", { className: "font-semibold", children: value })
10334
+ ] }),
10335
+ secondaryLabel && /* @__PURE__ */ jsxs40("div", { className: "text-muted-foreground text-xs mt-1", children: [
10336
+ secondaryLabel,
10337
+ ": ",
10338
+ secondaryValue
10339
+ ] })
10340
+ ] })
10341
+ ]
10342
+ }
10343
+ ),
10344
+ /* @__PURE__ */ jsx45("style", { children: `
10345
+ @keyframes chartTooltipFadeIn {
10346
+ from { opacity: 0; transform: translateX(-5px); }
10347
+ to { opacity: 1; transform: translateX(0); }
10348
+ }
10349
+ ` })
10350
+ ]
10351
+ }
10352
+ );
10353
+ return createPortal10(tooltipContent, document.body);
10354
+ }
10355
+
10356
+ // ../../components/ui/LineChart.tsx
10357
+ import { Fragment as Fragment17, jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
10358
+ function LineChart({
10359
+ data,
10360
+ width = 400,
10361
+ height = 200,
10362
+ color = "currentColor",
10363
+ fillColor,
10364
+ showDots = true,
10365
+ showGrid = true,
10366
+ showLabels = true,
10367
+ showValues = false,
10368
+ animated = true,
10369
+ curved = true,
10370
+ className = ""
10371
+ }) {
10372
+ const svgRef = useRef14(null);
10373
+ const padding = { top: 20, right: 20, bottom: 40, left: 40 };
10374
+ const chartWidth = width - padding.left - padding.right;
10375
+ const chartHeight = height - padding.top - padding.bottom;
10376
+ const [hoveredPoint, setHoveredPoint] = useState33(null);
10377
+ const { minValue, maxValue, points, linePath, areaPath } = useMemo6(() => {
10378
+ if (!data.length) return { minValue: 0, maxValue: 0, points: [], linePath: "", areaPath: "" };
10379
+ const values = data.map((d) => d.value);
10380
+ const min = Math.min(...values);
10381
+ const max = Math.max(...values);
10382
+ const range = max - min || 1;
10383
+ const pts = data.map((d, i) => ({
10384
+ x: padding.left + i / (data.length - 1 || 1) * chartWidth,
10385
+ y: padding.top + chartHeight - (d.value - min) / range * chartHeight,
10386
+ ...d
10387
+ }));
10388
+ let path = "";
10389
+ let area = "";
10390
+ if (curved && pts.length > 2) {
10391
+ path = `M ${pts[0].x} ${pts[0].y}`;
10392
+ area = `M ${pts[0].x} ${padding.top + chartHeight} L ${pts[0].x} ${pts[0].y}`;
10393
+ for (let i = 0; i < pts.length - 1; i++) {
10394
+ const p0 = pts[Math.max(0, i - 1)];
10395
+ const p1 = pts[i];
10396
+ const p2 = pts[i + 1];
10397
+ const p3 = pts[Math.min(pts.length - 1, i + 2)];
10398
+ const cp1x = p1.x + (p2.x - p0.x) / 6;
10399
+ const cp1y = p1.y + (p2.y - p0.y) / 6;
10400
+ const cp2x = p2.x - (p3.x - p1.x) / 6;
10401
+ const cp2y = p2.y - (p3.y - p1.y) / 6;
10402
+ path += ` C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${p2.x} ${p2.y}`;
10403
+ area += ` C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${p2.x} ${p2.y}`;
10404
+ }
10405
+ area += ` L ${pts[pts.length - 1].x} ${padding.top + chartHeight} Z`;
10406
+ } else {
10407
+ path = pts.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ");
10408
+ area = `M ${pts[0].x} ${padding.top + chartHeight} ` + pts.map((p) => `L ${p.x} ${p.y}`).join(" ") + ` L ${pts[pts.length - 1].x} ${padding.top + chartHeight} Z`;
10409
+ }
10410
+ return { minValue: min, maxValue: max, points: pts, linePath: path, areaPath: area };
10411
+ }, [data, chartWidth, chartHeight, curved, padding.left, padding.top]);
10412
+ const gridLines = useMemo6(() => {
10413
+ const lines = [];
10414
+ const steps = 5;
10415
+ for (let i = 0; i <= steps; i++) {
10416
+ const y = padding.top + i / steps * chartHeight;
10417
+ const value = maxValue - i / steps * (maxValue - minValue);
10418
+ lines.push({ y, value });
10419
+ }
10420
+ return lines;
10421
+ }, [minValue, maxValue, chartHeight, padding.top]);
10422
+ return /* @__PURE__ */ jsxs41(Fragment17, { children: [
10423
+ /* @__PURE__ */ jsxs41("svg", { ref: svgRef, width, height, className: `overflow-visible ${className}`, style: { fontFamily: "inherit" }, children: [
10424
+ showGrid && /* @__PURE__ */ jsx46("g", { className: "text-muted-foreground/20", children: gridLines.map((line, i) => /* @__PURE__ */ jsxs41("g", { children: [
10425
+ /* @__PURE__ */ jsx46("line", { x1: padding.left, y1: line.y, x2: width - padding.right, y2: line.y, stroke: "currentColor", strokeDasharray: "4 4" }),
10426
+ /* @__PURE__ */ jsx46("text", { x: padding.left - 8, y: line.y + 4, textAnchor: "end", fontSize: "10", fill: "currentColor", className: "text-muted-foreground", children: line.value.toFixed(0) })
10427
+ ] }, i)) }),
10428
+ fillColor && areaPath && /* @__PURE__ */ jsx46("path", { d: areaPath, fill: fillColor, opacity: 0.2, className: animated ? "animate-[fadeIn_0.6s_ease-out]" : "" }),
10429
+ linePath && /* @__PURE__ */ jsx46(
10430
+ "path",
10431
+ {
10432
+ d: linePath,
10433
+ fill: "none",
10434
+ stroke: color,
10435
+ strokeWidth: 2,
10436
+ strokeLinecap: "round",
10437
+ strokeLinejoin: "round",
10438
+ className: animated ? "animate-[drawLine_1s_ease-out]" : "",
10439
+ style: animated ? {
10440
+ strokeDasharray: 1e3,
10441
+ strokeDashoffset: 0,
10442
+ animation: "drawLine 1s ease-out forwards"
10443
+ } : void 0
10444
+ }
10445
+ ),
10446
+ showDots && points.map((point, i) => /* @__PURE__ */ jsxs41(
10447
+ "g",
10448
+ {
10449
+ onMouseEnter: () => setHoveredPoint({ x: point.x, y: point.y, label: point.label, value: point.value }),
10450
+ onMouseLeave: () => setHoveredPoint(null),
10451
+ className: "cursor-pointer",
10452
+ children: [
10453
+ /* @__PURE__ */ jsx46(
10454
+ "circle",
10455
+ {
10456
+ cx: point.x,
10457
+ cy: point.y,
10458
+ r: hoveredPoint?.x === point.x ? 6 : 4,
10459
+ fill: color,
10460
+ className: `transition-all duration-150 ${animated ? "animate-[scaleIn_0.3s_ease-out]" : ""}`,
10461
+ style: animated ? { animationDelay: `${i * 0.05}s`, animationFillMode: "both" } : void 0
10462
+ }
10463
+ ),
10464
+ /* @__PURE__ */ jsx46("circle", { cx: point.x, cy: point.y, r: 16, fill: "transparent" }),
10465
+ showValues && /* @__PURE__ */ jsx46("text", { x: point.x, y: point.y - 12, textAnchor: "middle", fontSize: "10", fontWeight: "500", className: "text-foreground", fill: "currentColor", children: point.value })
10466
+ ]
10467
+ },
10468
+ i
10469
+ )),
10470
+ hoveredPoint && /* @__PURE__ */ jsxs41("g", { className: "pointer-events-none", children: [
10471
+ /* @__PURE__ */ jsx46(
10472
+ "line",
10473
+ {
10474
+ x1: hoveredPoint.x,
10475
+ y1: padding.top,
10476
+ x2: hoveredPoint.x,
10477
+ y2: padding.top + chartHeight,
10478
+ stroke: color,
10479
+ strokeWidth: 1,
10480
+ strokeDasharray: "4 4",
10481
+ opacity: 0.5
10482
+ }
10483
+ ),
10484
+ /* @__PURE__ */ jsx46(
10485
+ "line",
10486
+ {
10487
+ x1: padding.left,
10488
+ y1: hoveredPoint.y,
10489
+ x2: padding.left + chartWidth,
10490
+ y2: hoveredPoint.y,
10491
+ stroke: color,
10492
+ strokeWidth: 1,
10493
+ strokeDasharray: "4 4",
10494
+ opacity: 0.5
10495
+ }
10496
+ )
10497
+ ] }),
10498
+ showLabels && points.map((point, i) => /* @__PURE__ */ jsx46("text", { x: point.x, y: height - 10, textAnchor: "middle", fontSize: "10", className: "text-muted-foreground", fill: "currentColor", children: point.label }, i)),
10499
+ /* @__PURE__ */ jsx46("style", { children: `
10500
+ @keyframes drawLine {
10501
+ from { stroke-dashoffset: 1000; }
10502
+ to { stroke-dashoffset: 0; }
10503
+ }
10504
+ @keyframes scaleIn {
10505
+ from { transform: scale(0); opacity: 0; }
10506
+ to { transform: scale(1); opacity: 1; }
10507
+ }
10508
+ @keyframes fadeIn {
10509
+ from { opacity: 0; }
10510
+ to { opacity: 0.2; }
10511
+ }
10512
+ ` })
10513
+ ] }),
10514
+ /* @__PURE__ */ jsx46(
10515
+ ChartTooltip,
10516
+ {
10517
+ x: hoveredPoint?.x ?? 0,
10518
+ y: hoveredPoint?.y ?? 0,
10519
+ visible: !!hoveredPoint,
10520
+ label: hoveredPoint?.label,
10521
+ value: hoveredPoint?.value,
10522
+ color,
10523
+ containerRef: svgRef
10524
+ }
10525
+ )
10526
+ ] });
10527
+ }
10528
+
10529
+ // ../../components/ui/BarChart.tsx
10530
+ import { useMemo as useMemo7, useState as useState34, useRef as useRef15 } from "react";
10531
+ import { Fragment as Fragment18, jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
10532
+ function BarChart({
10533
+ data,
10534
+ width = 400,
10535
+ height = 200,
10536
+ color = "currentColor",
10537
+ showLabels = true,
10538
+ showValues = true,
10539
+ showGrid = true,
10540
+ horizontal = false,
10541
+ animated = true,
10542
+ barRadius = 4,
10543
+ barGap = 0.3,
10544
+ className = ""
10545
+ }) {
10546
+ const svgRef = useRef15(null);
10547
+ const padding = horizontal ? { top: 20, right: 40, bottom: 20, left: 80 } : { top: 20, right: 20, bottom: 40, left: 40 };
10548
+ const chartWidth = width - padding.left - padding.right;
10549
+ const chartHeight = height - padding.top - padding.bottom;
10550
+ const [hoveredBar, setHoveredBar] = useState34(null);
10551
+ const { maxValue, bars, gridLines } = useMemo7(() => {
10552
+ if (!data.length) return { maxValue: 0, bars: [], gridLines: [] };
10553
+ const max = Math.max(...data.map((d) => d.value));
10554
+ const barCount = data.length;
10555
+ const barsData = data.map((d, i) => {
10556
+ if (horizontal) {
10557
+ const barHeight = chartHeight / barCount * (1 - barGap);
10558
+ const gap = chartHeight / barCount * barGap;
10559
+ return {
10560
+ x: padding.left,
10561
+ y: padding.top + i * (barHeight + gap) + gap / 2,
10562
+ width: d.value / max * chartWidth,
10563
+ height: barHeight,
10564
+ ...d
10565
+ };
10566
+ } else {
10567
+ const barWidth = chartWidth / barCount * (1 - barGap);
10568
+ const gap = chartWidth / barCount * barGap;
10569
+ return {
10570
+ x: padding.left + i * (barWidth + gap) + gap / 2,
10571
+ y: padding.top + chartHeight - d.value / max * chartHeight,
10572
+ width: barWidth,
10573
+ height: d.value / max * chartHeight,
10574
+ ...d
10575
+ };
10576
+ }
10577
+ });
10578
+ const lines = [];
10579
+ const steps = 5;
10580
+ for (let i = 0; i <= steps; i++) {
10581
+ const value = i / steps * max;
10582
+ if (horizontal) {
10583
+ lines.push({
10584
+ x: padding.left + i / steps * chartWidth,
10585
+ y1: padding.top,
10586
+ y2: height - padding.bottom,
10587
+ value
10588
+ });
10589
+ } else {
10590
+ lines.push({
10591
+ y: padding.top + chartHeight - i / steps * chartHeight,
10592
+ x1: padding.left,
10593
+ x2: width - padding.right,
10594
+ value
10595
+ });
10596
+ }
10597
+ }
10598
+ return { maxValue: max, bars: barsData, gridLines: lines };
10599
+ }, [data, chartWidth, chartHeight, horizontal, barGap, padding, width, height]);
10600
+ return /* @__PURE__ */ jsxs42(Fragment18, { children: [
10601
+ /* @__PURE__ */ jsxs42("svg", { ref: svgRef, width, height, className: `overflow-visible ${className}`, style: { fontFamily: "inherit" }, children: [
10602
+ showGrid && /* @__PURE__ */ jsx47("g", { className: "text-muted-foreground/20", children: gridLines.map((line, i) => /* @__PURE__ */ jsx47("g", { children: horizontal ? /* @__PURE__ */ jsxs42(Fragment18, { children: [
10603
+ /* @__PURE__ */ jsx47("line", { x1: line.x, y1: line.y1, x2: line.x, y2: line.y2, stroke: "currentColor", strokeDasharray: "4 4" }),
10604
+ /* @__PURE__ */ jsx47("text", { x: line.x, y: height - 8, textAnchor: "middle", fontSize: "10", className: "text-muted-foreground", fill: "currentColor", children: line.value.toFixed(0) })
10605
+ ] }) : /* @__PURE__ */ jsxs42(Fragment18, { children: [
10606
+ /* @__PURE__ */ jsx47("line", { x1: line.x1, y1: line.y, x2: line.x2, y2: line.y, stroke: "currentColor", strokeDasharray: "4 4" }),
10607
+ /* @__PURE__ */ jsx47("text", { x: padding.left - 8, y: line.y + 4, textAnchor: "end", fontSize: "10", className: "text-muted-foreground", fill: "currentColor", children: line.value.toFixed(0) })
10608
+ ] }) }, i)) }),
10609
+ bars.map((bar, i) => /* @__PURE__ */ jsxs42(
10610
+ "g",
10611
+ {
10612
+ onMouseEnter: () => setHoveredBar({
10613
+ x: horizontal ? bar.x + bar.width : bar.x + bar.width / 2,
10614
+ y: horizontal ? bar.y + bar.height / 2 : bar.y,
10615
+ label: bar.label,
10616
+ value: bar.value,
10617
+ color: bar.color || color
10618
+ }),
10619
+ onMouseLeave: () => setHoveredBar(null),
10620
+ className: "cursor-pointer",
10621
+ children: [
10622
+ /* @__PURE__ */ jsxs42(
10623
+ "rect",
10624
+ {
10625
+ x: bar.x,
10626
+ y: horizontal ? bar.y : bar.y,
10627
+ width: animated && !horizontal ? 0 : bar.width,
10628
+ height: animated && horizontal ? bar.height : horizontal ? bar.height : 0,
10629
+ rx: barRadius,
10630
+ ry: barRadius,
10631
+ fill: bar.color || color,
10632
+ className: `transition-all duration-150 ${hoveredBar?.label === bar.label ? "opacity-80" : ""}`,
10633
+ style: animated ? {
10634
+ animation: horizontal ? `growWidth 0.5s ease-out ${i * 0.1}s forwards` : `growHeight 0.5s ease-out ${i * 0.1}s forwards`,
10635
+ ...horizontal ? { width: 0 } : { height: 0, y: padding.top + chartHeight }
10636
+ } : void 0,
10637
+ children: [
10638
+ /* @__PURE__ */ jsx47(
10639
+ "animate",
10640
+ {
10641
+ attributeName: horizontal ? "width" : "height",
10642
+ from: "0",
10643
+ to: horizontal ? bar.width : bar.height,
10644
+ dur: "0.5s",
10645
+ begin: `${i * 0.1}s`,
10646
+ fill: "freeze"
10647
+ }
10648
+ ),
10649
+ !horizontal && /* @__PURE__ */ jsx47("animate", { attributeName: "y", from: padding.top + chartHeight, to: bar.y, dur: "0.5s", begin: `${i * 0.1}s`, fill: "freeze" })
10650
+ ]
10651
+ }
10652
+ ),
10653
+ showValues && /* @__PURE__ */ jsx47(
10654
+ "text",
10655
+ {
10656
+ x: horizontal ? bar.x + bar.width + 8 : bar.x + bar.width / 2,
10657
+ y: horizontal ? bar.y + bar.height / 2 + 4 : bar.y - 8,
10658
+ textAnchor: horizontal ? "start" : "middle",
10659
+ fontSize: "11",
10660
+ fontWeight: "500",
10661
+ className: "text-foreground",
10662
+ fill: "currentColor",
10663
+ style: animated ? { opacity: 0, animation: `fadeIn 0.3s ease-out ${i * 0.1 + 0.3}s forwards` } : void 0,
10664
+ children: bar.value
10665
+ }
10666
+ ),
10667
+ showLabels && /* @__PURE__ */ jsx47(
10668
+ "text",
10669
+ {
10670
+ x: horizontal ? padding.left - 8 : bar.x + bar.width / 2,
10671
+ y: horizontal ? bar.y + bar.height / 2 + 4 : height - 10,
10672
+ textAnchor: horizontal ? "end" : "middle",
10673
+ fontSize: "10",
10674
+ className: "text-muted-foreground",
10675
+ fill: "currentColor",
10676
+ children: bar.label
10677
+ }
10678
+ )
10679
+ ]
10680
+ },
10681
+ i
10682
+ )),
10683
+ /* @__PURE__ */ jsx47("style", { children: `
10684
+ @keyframes growHeight {
10685
+ from { height: 0; }
10686
+ }
10687
+ @keyframes growWidth {
10688
+ from { width: 0; }
10689
+ }
10690
+ @keyframes fadeIn {
10691
+ from { opacity: 0; }
10692
+ to { opacity: 1; }
10693
+ }
10694
+ ` })
10695
+ ] }),
10696
+ /* @__PURE__ */ jsx47(
10697
+ ChartTooltip,
10698
+ {
10699
+ x: hoveredBar?.x ?? 0,
10700
+ y: hoveredBar?.y ?? 0,
10701
+ visible: !!hoveredBar,
10702
+ label: hoveredBar?.label,
10703
+ value: hoveredBar?.value,
10704
+ color: hoveredBar?.color,
10705
+ containerRef: svgRef
10706
+ }
10707
+ )
10708
+ ] });
10709
+ }
10710
+
10711
+ // ../../components/ui/PieChart.tsx
10712
+ import { useMemo as useMemo8, useState as useState35, useRef as useRef16 } from "react";
10713
+ import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
10714
+ function PieChart({
10715
+ data,
10716
+ size = 200,
10717
+ donut = false,
10718
+ donutWidth = 40,
10719
+ showLabels = true,
10720
+ showLegend = true,
10721
+ showPercentage = true,
10722
+ animated = true,
10723
+ startAngle = -90,
10724
+ className = ""
10725
+ }) {
10726
+ const containerRef = useRef16(null);
10727
+ const center = size / 2;
10728
+ const radius = size / 2 - 10;
10729
+ const innerRadius = donut ? radius - donutWidth : 0;
10730
+ const { segments, total } = useMemo8(() => {
10731
+ if (!data.length) return { segments: [], total: 0 };
10732
+ const sum = data.reduce((acc, d) => acc + d.value, 0);
10733
+ let currentAngle = startAngle;
10734
+ const segs = data.map((d, i) => {
10735
+ const percentage = d.value / sum;
10736
+ const angle = percentage * 360;
10737
+ const startRad = currentAngle * Math.PI / 180;
10738
+ const endRad = (currentAngle + angle) * Math.PI / 180;
10739
+ const midRad = (currentAngle + angle / 2) * Math.PI / 180;
10740
+ const largeArc = angle > 180 ? 1 : 0;
10741
+ const x1 = center + radius * Math.cos(startRad);
10742
+ const y1 = center + radius * Math.sin(startRad);
10743
+ const x2 = center + radius * Math.cos(endRad);
10744
+ const y2 = center + radius * Math.sin(endRad);
10745
+ const x3 = center + innerRadius * Math.cos(endRad);
10746
+ const y3 = center + innerRadius * Math.sin(endRad);
10747
+ const x4 = center + innerRadius * Math.cos(startRad);
10748
+ const y4 = center + innerRadius * Math.sin(startRad);
10749
+ const labelRadius = radius + 20;
10750
+ const labelX = center + labelRadius * Math.cos(midRad);
10751
+ const labelY = center + labelRadius * Math.sin(midRad);
10752
+ let path;
10753
+ if (donut) {
10754
+ path = [
10755
+ `M ${x1} ${y1}`,
10756
+ `A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2}`,
10757
+ `L ${x3} ${y3}`,
10758
+ `A ${innerRadius} ${innerRadius} 0 ${largeArc} 0 ${x4} ${y4}`,
10759
+ "Z"
10760
+ ].join(" ");
10761
+ } else {
10762
+ path = [`M ${center} ${center}`, `L ${x1} ${y1}`, `A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2}`, "Z"].join(" ");
10763
+ }
10764
+ currentAngle += angle;
10765
+ return {
10766
+ path,
10767
+ ...d,
10768
+ percentage,
10769
+ labelX,
10770
+ labelY,
10771
+ midAngle: currentAngle - angle / 2
10772
+ };
10773
+ });
10774
+ return { segments: segs, total: sum };
10775
+ }, [data, center, radius, innerRadius, donut, startAngle]);
10776
+ const [hoveredSegment, setHoveredSegment] = useState35(null);
10777
+ return /* @__PURE__ */ jsxs43("div", { ref: containerRef, className: `relative flex items-center gap-6 ${className}`, children: [
10778
+ /* @__PURE__ */ jsxs43("svg", { width: size + 40, height: size + 40, className: "overflow-visible", style: { fontFamily: "inherit" }, children: [
10779
+ /* @__PURE__ */ jsxs43("g", { transform: `translate(20, 20)`, children: [
10780
+ segments.map((seg, i) => /* @__PURE__ */ jsxs43(
10781
+ "g",
10782
+ {
10783
+ onMouseEnter: () => setHoveredSegment({
10784
+ x: seg.labelX + 20,
10785
+ y: seg.labelY + 20,
10786
+ label: seg.label,
10787
+ value: seg.value,
10788
+ percentage: seg.percentage,
10789
+ color: seg.color
10790
+ }),
10791
+ onMouseLeave: () => setHoveredSegment(null),
10792
+ children: [
10793
+ /* @__PURE__ */ jsx48(
10794
+ "path",
10795
+ {
10796
+ d: seg.path,
10797
+ fill: seg.color,
10798
+ className: `transition-all duration-150 cursor-pointer ${hoveredSegment?.label === seg.label ? "opacity-80" : ""}`,
10799
+ style: {
10800
+ transformOrigin: `${center}px ${center}px`,
10801
+ transform: hoveredSegment?.label === seg.label ? "scale(1.05)" : "scale(1)",
10802
+ ...animated ? {
10803
+ opacity: hoveredSegment?.label === seg.label ? 0.8 : 0,
10804
+ animation: `pieSlice 0.5s ease-out ${i * 0.1}s forwards`
10805
+ } : void 0
10806
+ }
10807
+ }
10808
+ ),
10809
+ showLabels && /* @__PURE__ */ jsx48(
10810
+ "text",
10811
+ {
10812
+ x: seg.labelX,
10813
+ y: seg.labelY,
10814
+ textAnchor: seg.labelX > center ? "start" : "end",
10815
+ fontSize: "10",
10816
+ className: "text-foreground",
10817
+ fill: "currentColor",
10818
+ style: animated ? { opacity: 0, animation: `fadeIn 0.3s ease-out ${i * 0.1 + 0.3}s forwards` } : void 0,
10819
+ children: showPercentage ? `${(seg.percentage * 100).toFixed(0)}%` : seg.value
10820
+ }
10821
+ )
10822
+ ]
10823
+ },
10824
+ i
10825
+ )),
10826
+ donut && /* @__PURE__ */ jsxs43("g", { children: [
10827
+ /* @__PURE__ */ jsx48("text", { x: center, y: center - 5, textAnchor: "middle", fontSize: "12", className: "text-muted-foreground", fill: "currentColor", children: "Total" }),
10828
+ /* @__PURE__ */ jsx48("text", { x: center, y: center + 15, textAnchor: "middle", fontSize: "18", fontWeight: "600", className: "text-foreground", fill: "currentColor", children: total })
10829
+ ] })
10830
+ ] }),
10831
+ /* @__PURE__ */ jsx48("style", { children: `
10832
+ @keyframes pieSlice {
10833
+ from {
10834
+ opacity: 0;
10835
+ transform: scale(0);
10836
+ }
10837
+ to {
10838
+ opacity: 1;
10839
+ transform: scale(1);
10840
+ }
10841
+ }
10842
+ @keyframes fadeIn {
10843
+ from { opacity: 0; }
10844
+ to { opacity: 1; }
10845
+ }
10846
+ ` })
10847
+ ] }),
10848
+ showLegend && /* @__PURE__ */ jsx48("div", { className: "flex flex-col gap-2", children: segments.map((seg, i) => /* @__PURE__ */ jsxs43(
10849
+ "div",
10850
+ {
10851
+ className: "flex items-center gap-2 text-sm",
10852
+ style: animated ? { opacity: 0, animation: `fadeIn 0.3s ease-out ${i * 0.1 + 0.3}s forwards` } : void 0,
10853
+ children: [
10854
+ /* @__PURE__ */ jsx48("div", { className: "w-3 h-3 rounded-sm shrink-0", style: { backgroundColor: seg.color } }),
10855
+ /* @__PURE__ */ jsx48("span", { className: "text-muted-foreground", children: seg.label }),
10856
+ /* @__PURE__ */ jsx48("span", { className: "text-foreground font-medium ml-auto", children: showPercentage ? `${(seg.percentage * 100).toFixed(0)}%` : seg.value })
10857
+ ]
10858
+ },
10859
+ i
10860
+ )) }),
10861
+ /* @__PURE__ */ jsx48(
10862
+ ChartTooltip,
10863
+ {
10864
+ x: hoveredSegment?.x ?? center,
10865
+ y: hoveredSegment?.y ?? center,
10866
+ visible: !!hoveredSegment,
10867
+ label: hoveredSegment?.label,
10868
+ value: `${hoveredSegment?.value} (${((hoveredSegment?.percentage ?? 0) * 100).toFixed(1)}%)`,
10869
+ color: hoveredSegment?.color,
10870
+ containerRef
10871
+ }
10872
+ )
10873
+ ] });
10874
+ }
10875
+
10876
+ // ../../components/ui/AreaChart.tsx
10877
+ import { useMemo as useMemo9, useState as useState36, useRef as useRef17 } from "react";
10878
+ import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
10879
+ function getCatmullRomSpline(points) {
10880
+ if (points.length < 2) return "";
10881
+ if (points.length === 2) {
10882
+ return `M ${points[0].x} ${points[0].y} L ${points[1].x} ${points[1].y}`;
10883
+ }
10884
+ let path = `M ${points[0].x} ${points[0].y}`;
10885
+ for (let i = 0; i < points.length - 1; i++) {
10886
+ const p0 = points[Math.max(0, i - 1)];
10887
+ const p1 = points[i];
10888
+ const p2 = points[i + 1];
10889
+ const p3 = points[Math.min(points.length - 1, i + 2)];
10890
+ const tension = 0.5;
10891
+ const cp1x = p1.x + (p2.x - p0.x) * tension / 6;
10892
+ const cp1y = p1.y + (p2.y - p0.y) * tension / 6;
10893
+ const cp2x = p2.x - (p3.x - p1.x) * tension / 6;
10894
+ const cp2y = p2.y - (p3.y - p1.y) * tension / 6;
10895
+ path += ` C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${p2.x} ${p2.y}`;
10896
+ }
10897
+ return path;
10898
+ }
10899
+ function AreaChart({
10900
+ series,
10901
+ width = 400,
10902
+ height = 200,
10903
+ showDots = true,
10904
+ showGrid = true,
10905
+ showLabels = true,
10906
+ showLegend = true,
10907
+ animated = true,
10908
+ stacked = false,
10909
+ curved = true,
10910
+ className = ""
10911
+ }) {
10912
+ const containerRef = useRef17(null);
10913
+ const padding = { top: 20, right: 20, bottom: 40, left: 50 };
10914
+ const chartWidth = width - padding.left - padding.right;
10915
+ const chartHeight = height - padding.top - padding.bottom;
10916
+ const [hoveredPoint, setHoveredPoint] = useState36(null);
10917
+ const { processedSeries, gridLines, maxValue, labels } = useMemo9(() => {
10918
+ if (!series.length || !series[0]?.data?.length) {
10919
+ return { processedSeries: [], gridLines: [], maxValue: 0, labels: [] };
10920
+ }
10921
+ const allLabels = series[0].data.map((d) => d.label);
10922
+ const dataLength = series[0].data.length;
10923
+ let max = 0;
10924
+ if (stacked) {
10925
+ for (let i = 0; i < dataLength; i++) {
10926
+ const stackedValue = series.reduce((sum, s) => sum + (s.data[i]?.value || 0), 0);
10927
+ max = Math.max(max, stackedValue);
10928
+ }
10929
+ } else {
10930
+ max = Math.max(...series.flatMap((s) => s.data.map((d) => d.value)));
10931
+ }
10932
+ const processed = series.map((s, seriesIndex) => {
10933
+ const points = s.data.map((d, i) => {
10934
+ const x = padding.left + i / (dataLength - 1) * chartWidth;
10935
+ let y;
10936
+ if (stacked && seriesIndex > 0) {
10937
+ const stackedBase = series.slice(0, seriesIndex).reduce((sum, prevS) => sum + (prevS.data[i]?.value || 0), 0);
10938
+ const stackedValue = stackedBase + d.value;
10939
+ y = padding.top + chartHeight - stackedValue / max * chartHeight;
10940
+ } else {
10941
+ y = padding.top + chartHeight - d.value / max * chartHeight;
10942
+ }
10943
+ return { x, y, value: d.value, label: d.label };
10944
+ });
10945
+ const linePath = curved ? getCatmullRomSpline(points) : `M ${points.map((p) => `${p.x} ${p.y}`).join(" L ")}`;
10946
+ let areaPath;
10947
+ if (stacked && seriesIndex > 0) {
10948
+ const prevSeriesPoints = series.slice(0, seriesIndex).reduce((acc, prevS) => {
10949
+ return prevS.data.map((d, i) => {
10950
+ const prevVal = acc[i] || 0;
10951
+ return prevVal + d.value;
10952
+ });
10953
+ }, []).map((val, i) => ({
10954
+ x: padding.left + i / (dataLength - 1) * chartWidth,
10955
+ y: padding.top + chartHeight - val / max * chartHeight
10956
+ }));
10957
+ const reversedPrevPoints = [...prevSeriesPoints].reverse();
10958
+ areaPath = `${linePath} L ${reversedPrevPoints.map((p) => `${p.x} ${p.y}`).join(" L ")} Z`;
10959
+ } else {
10960
+ areaPath = `${linePath} L ${padding.left + chartWidth} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
10961
+ }
10962
+ return {
10963
+ ...s,
10964
+ points,
10965
+ linePath,
10966
+ areaPath,
10967
+ lineLength: points.reduce((acc, p, i) => {
10968
+ if (i === 0) return 0;
10969
+ const prev = points[i - 1];
10970
+ return acc + Math.sqrt(Math.pow(p.x - prev.x, 2) + Math.pow(p.y - prev.y, 2));
10971
+ }, 0)
10972
+ };
10973
+ });
10974
+ const lines = [];
10975
+ const steps = 5;
10976
+ for (let i = 0; i <= steps; i++) {
10977
+ const value = i / steps * max;
10978
+ lines.push({
10979
+ y: padding.top + chartHeight - i / steps * chartHeight,
10980
+ value
10981
+ });
10982
+ }
10983
+ return { processedSeries: processed, gridLines: lines, maxValue: max, labels: allLabels };
10984
+ }, [series, chartWidth, chartHeight, padding, stacked, curved]);
10985
+ return /* @__PURE__ */ jsxs44("div", { ref: containerRef, className: `relative flex flex-col gap-4 ${className}`, children: [
10986
+ /* @__PURE__ */ jsxs44("svg", { width, height, className: "overflow-visible", style: { fontFamily: "inherit" }, children: [
10987
+ showGrid && /* @__PURE__ */ jsx49("g", { className: "text-muted-foreground/20", children: gridLines.map((line, i) => /* @__PURE__ */ jsxs44("g", { children: [
10988
+ /* @__PURE__ */ jsx49("line", { x1: padding.left, y1: line.y, x2: width - padding.right, y2: line.y, stroke: "currentColor", strokeDasharray: "4 4" }),
10989
+ /* @__PURE__ */ jsx49("text", { x: padding.left - 8, y: line.y + 4, textAnchor: "end", fontSize: "10", className: "text-muted-foreground", fill: "currentColor", children: line.value.toFixed(0) })
10990
+ ] }, i)) }),
10991
+ [...processedSeries].reverse().map((s, i) => /* @__PURE__ */ jsx49(
10992
+ "path",
10993
+ {
10994
+ d: s.areaPath,
10995
+ fill: s.color,
10996
+ fillOpacity: s.fillOpacity ?? 0.3,
10997
+ className: "transition-all duration-300",
10998
+ style: animated ? {
10999
+ opacity: 0,
11000
+ animation: `fadeIn 0.5s ease-out ${i * 0.1}s forwards`
11001
+ } : void 0
11002
+ },
11003
+ `area-${i}`
11004
+ )),
11005
+ processedSeries.map((s, i) => /* @__PURE__ */ jsx49(
11006
+ "path",
11007
+ {
11008
+ d: s.linePath,
11009
+ fill: "none",
11010
+ stroke: s.color,
11011
+ strokeWidth: 2,
11012
+ strokeLinecap: "round",
11013
+ strokeLinejoin: "round",
11014
+ style: animated ? {
11015
+ strokeDasharray: s.lineLength,
11016
+ strokeDashoffset: s.lineLength,
11017
+ animation: `drawLine 1s ease-out ${i * 0.1}s forwards`
11018
+ } : void 0
11019
+ },
11020
+ `line-${i}`
11021
+ )),
11022
+ showDots && processedSeries.map(
11023
+ (s, seriesIdx) => s.points.map((point, i) => /* @__PURE__ */ jsxs44(
11024
+ "g",
11025
+ {
11026
+ onMouseEnter: () => {
11027
+ const items = processedSeries.map((ps) => ({
11028
+ label: ps.name,
11029
+ value: ps.points[i]?.value ?? 0,
11030
+ color: ps.color
11031
+ }));
11032
+ setHoveredPoint({
11033
+ x: point.x,
11034
+ y: point.y,
11035
+ label: point.label,
11036
+ items
11037
+ });
11038
+ },
11039
+ onMouseLeave: () => setHoveredPoint(null),
11040
+ className: "cursor-pointer",
11041
+ children: [
11042
+ /* @__PURE__ */ jsx49(
11043
+ "circle",
11044
+ {
11045
+ cx: point.x,
11046
+ cy: point.y,
11047
+ r: hoveredPoint?.x === point.x ? 6 : 4,
11048
+ fill: s.color,
11049
+ className: "transition-all duration-150",
11050
+ style: animated ? {
11051
+ transform: "scale(0)",
11052
+ opacity: 0,
11053
+ transformOrigin: `${point.x}px ${point.y}px`,
11054
+ animation: `dotPop 0.3s ease-out ${seriesIdx * 0.1 + i * 0.05 + 0.5}s forwards`
11055
+ } : void 0
11056
+ }
11057
+ ),
11058
+ /* @__PURE__ */ jsx49("circle", { cx: point.x, cy: point.y, r: 12, fill: "transparent" })
11059
+ ]
11060
+ },
11061
+ `dot-${seriesIdx}-${i}`
11062
+ ))
11063
+ ),
11064
+ showLabels && /* @__PURE__ */ jsx49("g", { className: "text-muted-foreground", children: labels.map((label, i) => {
11065
+ const x = padding.left + i / (labels.length - 1) * chartWidth;
11066
+ return /* @__PURE__ */ jsx49("text", { x, y: height - 10, textAnchor: "middle", fontSize: "10", fill: "currentColor", children: label }, i);
11067
+ }) }),
11068
+ hoveredPoint && /* @__PURE__ */ jsx49("g", { className: "pointer-events-none", children: /* @__PURE__ */ jsx49(
11069
+ "line",
11070
+ {
11071
+ x1: hoveredPoint.x,
11072
+ y1: padding.top,
11073
+ x2: hoveredPoint.x,
11074
+ y2: padding.top + chartHeight,
11075
+ stroke: "currentColor",
11076
+ strokeWidth: 1,
11077
+ strokeDasharray: "4 4",
11078
+ opacity: 0.3,
11079
+ className: "text-foreground"
11080
+ }
11081
+ ) }),
11082
+ /* @__PURE__ */ jsx49("style", { children: `
11083
+ @keyframes drawLine {
11084
+ to {
11085
+ stroke-dashoffset: 0;
11086
+ }
11087
+ }
11088
+ @keyframes fadeIn {
11089
+ from { opacity: 0; }
11090
+ to { opacity: 1; }
11091
+ }
11092
+ @keyframes dotPop {
11093
+ from {
11094
+ transform: scale(0);
11095
+ opacity: 0;
11096
+ }
11097
+ to {
11098
+ transform: scale(1);
11099
+ opacity: 1;
11100
+ }
11101
+ }
11102
+ ` })
11103
+ ] }),
11104
+ showLegend && /* @__PURE__ */ jsx49("div", { className: "flex items-center justify-center gap-6", children: series.map((s, i) => /* @__PURE__ */ jsxs44(
11105
+ "div",
11106
+ {
11107
+ className: "flex items-center gap-2 text-sm",
11108
+ style: animated ? { opacity: 0, animation: `fadeIn 0.3s ease-out ${i * 0.1 + 0.5}s forwards` } : void 0,
11109
+ children: [
11110
+ /* @__PURE__ */ jsx49("div", { className: "w-3 h-3 rounded-sm", style: { backgroundColor: s.color } }),
11111
+ /* @__PURE__ */ jsx49("span", { className: "text-muted-foreground", children: s.name })
11112
+ ]
11113
+ },
11114
+ i
11115
+ )) }),
11116
+ /* @__PURE__ */ jsx49(
11117
+ ChartTooltip,
11118
+ {
11119
+ x: hoveredPoint?.x ?? 0,
11120
+ y: hoveredPoint?.y ?? 0,
11121
+ visible: !!hoveredPoint,
11122
+ label: hoveredPoint?.label,
11123
+ items: hoveredPoint?.items,
11124
+ containerRef
11125
+ }
11126
+ )
11127
+ ] });
11128
+ }
11129
+
11130
+ // ../../components/ui/Sparkline.tsx
11131
+ import { useMemo as useMemo10 } from "react";
11132
+ import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
11133
+ function getCatmullRomSpline2(points) {
11134
+ if (points.length < 2) return "";
11135
+ if (points.length === 2) {
11136
+ return `M ${points[0].x} ${points[0].y} L ${points[1].x} ${points[1].y}`;
11137
+ }
11138
+ let path = `M ${points[0].x} ${points[0].y}`;
11139
+ for (let i = 0; i < points.length - 1; i++) {
11140
+ const p0 = points[Math.max(0, i - 1)];
11141
+ const p1 = points[i];
11142
+ const p2 = points[i + 1];
11143
+ const p3 = points[Math.min(points.length - 1, i + 2)];
11144
+ const tension = 0.5;
11145
+ const cp1x = p1.x + (p2.x - p0.x) * tension / 6;
11146
+ const cp1y = p1.y + (p2.y - p0.y) * tension / 6;
11147
+ const cp2x = p2.x - (p3.x - p1.x) * tension / 6;
11148
+ const cp2y = p2.y - (p3.y - p1.y) * tension / 6;
11149
+ path += ` C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${p2.x} ${p2.y}`;
11150
+ }
11151
+ return path;
11152
+ }
11153
+ function Sparkline({
11154
+ data,
11155
+ width = 100,
11156
+ height = 30,
11157
+ color = "currentColor",
11158
+ fillColor,
11159
+ showFill = true,
11160
+ showDots = false,
11161
+ showEndDot = true,
11162
+ animated = true,
11163
+ curved = true,
11164
+ strokeWidth = 2,
11165
+ className = ""
11166
+ }) {
11167
+ const padding = 4;
11168
+ const chartWidth = width - padding * 2;
11169
+ const chartHeight = height - padding * 2;
11170
+ const { points, linePath, areaPath, lineLength, trend } = useMemo10(() => {
11171
+ const normalizedData = data.map((d) => typeof d === "number" ? d : d.value);
11172
+ if (!normalizedData.length) {
11173
+ return { points: [], linePath: "", areaPath: "", lineLength: 0, trend: 0 };
11174
+ }
11175
+ const min = Math.min(...normalizedData);
11176
+ const max = Math.max(...normalizedData);
11177
+ const range = max - min || 1;
11178
+ const pts = normalizedData.map((value, i) => ({
11179
+ x: padding + i / (normalizedData.length - 1) * chartWidth,
11180
+ y: padding + chartHeight - (value - min) / range * chartHeight,
11181
+ value
11182
+ }));
11183
+ const line = curved ? getCatmullRomSpline2(pts) : `M ${pts.map((p) => `${p.x} ${p.y}`).join(" L ")}`;
11184
+ const area = `${line} L ${padding + chartWidth} ${padding + chartHeight} L ${padding} ${padding + chartHeight} Z`;
11185
+ const length = pts.reduce((acc, p, i) => {
11186
+ if (i === 0) return 0;
11187
+ const prev = pts[i - 1];
11188
+ return acc + Math.sqrt(Math.pow(p.x - prev.x, 2) + Math.pow(p.y - prev.y, 2));
11189
+ }, 0);
11190
+ const trendValue = normalizedData[normalizedData.length - 1] - normalizedData[0];
11191
+ return { points: pts, linePath: line, areaPath: area, lineLength: length, trend: trendValue };
11192
+ }, [data, chartWidth, chartHeight, padding, curved]);
11193
+ const effectiveFillColor = fillColor || color;
11194
+ return /* @__PURE__ */ jsxs45("svg", { width, height, className: `overflow-visible ${className}`, style: { fontFamily: "inherit" }, children: [
11195
+ showFill && /* @__PURE__ */ jsx50(
11196
+ "path",
11197
+ {
11198
+ d: areaPath,
11199
+ fill: effectiveFillColor,
11200
+ fillOpacity: 0.1,
11201
+ style: animated ? { opacity: 0, animation: "fadeIn 0.5s ease-out 0.3s forwards" } : void 0
11202
+ }
11203
+ ),
11204
+ /* @__PURE__ */ jsx50(
11205
+ "path",
11206
+ {
11207
+ d: linePath,
11208
+ fill: "none",
11209
+ stroke: color,
11210
+ strokeWidth,
11211
+ strokeLinecap: "round",
11212
+ strokeLinejoin: "round",
11213
+ style: animated ? {
11214
+ strokeDasharray: lineLength,
11215
+ strokeDashoffset: lineLength,
11216
+ animation: "drawLine 0.8s ease-out forwards"
11217
+ } : void 0
11218
+ }
11219
+ ),
11220
+ showDots && points.map((point, i) => /* @__PURE__ */ jsx50(
11221
+ "circle",
11222
+ {
11223
+ cx: point.x,
11224
+ cy: point.y,
11225
+ r: 2,
11226
+ fill: color,
11227
+ style: animated ? {
11228
+ opacity: 0,
11229
+ animation: `fadeIn 0.3s ease-out ${i * 0.05 + 0.5}s forwards`
11230
+ } : void 0
11231
+ },
11232
+ i
11233
+ )),
11234
+ showEndDot && !showDots && points.length > 0 && /* @__PURE__ */ jsx50(
11235
+ "circle",
11236
+ {
11237
+ cx: points[points.length - 1].x,
11238
+ cy: points[points.length - 1].y,
11239
+ r: 3,
11240
+ fill: color,
11241
+ style: animated ? {
11242
+ opacity: 0,
11243
+ transform: "scale(0)",
11244
+ transformOrigin: `${points[points.length - 1].x}px ${points[points.length - 1].y}px`,
11245
+ animation: "dotPop 0.3s ease-out 0.6s forwards"
11246
+ } : void 0
11247
+ }
11248
+ ),
11249
+ /* @__PURE__ */ jsx50("style", { children: `
11250
+ @keyframes drawLine {
11251
+ to {
11252
+ stroke-dashoffset: 0;
11253
+ }
11254
+ }
11255
+ @keyframes fadeIn {
11256
+ from { opacity: 0; }
11257
+ to { opacity: 1; }
11258
+ }
11259
+ @keyframes dotPop {
11260
+ from {
11261
+ transform: scale(0);
11262
+ opacity: 0;
11263
+ }
11264
+ to {
11265
+ transform: scale(1);
11266
+ opacity: 1;
11267
+ }
11268
+ }
11269
+ ` })
11270
+ ] });
11271
+ }
11272
+
11273
+ // ../../components/ui/RadarChart.tsx
11274
+ import { useMemo as useMemo11, useState as useState37, useRef as useRef18 } from "react";
11275
+ import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
11276
+ function RadarChart({
11277
+ series,
11278
+ size = 300,
11279
+ levels = 5,
11280
+ showLabels = true,
11281
+ showLegend = true,
11282
+ showValues = false,
11283
+ animated = true,
11284
+ className = ""
11285
+ }) {
11286
+ const containerRef = useRef18(null);
11287
+ const center = size / 2;
11288
+ const radius = size / 2 - 40;
11289
+ const [hoveredPoint, setHoveredPoint] = useState37(null);
11290
+ const { axes, processedSeries, levelPaths } = useMemo11(() => {
11291
+ if (!series.length || !series[0]?.data?.length) {
11292
+ return { axes: [], processedSeries: [], levelPaths: [] };
11293
+ }
11294
+ const axisLabels = series[0].data.map((d) => d.axis);
11295
+ const axisCount = axisLabels.length;
11296
+ const angleStep = 2 * Math.PI / axisCount;
11297
+ const maxValue = Math.max(...series.flatMap((s) => s.data.map((d) => d.value)));
11298
+ const axesData = axisLabels.map((label, i) => {
11299
+ const angle = i * angleStep - Math.PI / 2;
11300
+ const x = center + radius * Math.cos(angle);
11301
+ const y = center + radius * Math.sin(angle);
11302
+ const labelX = center + (radius + 20) * Math.cos(angle);
11303
+ const labelY = center + (radius + 20) * Math.sin(angle);
11304
+ return { label, x, y, labelX, labelY, angle };
11305
+ });
11306
+ const levelsData = [];
11307
+ for (let l = 1; l <= levels; l++) {
11308
+ const levelRadius = l / levels * radius;
11309
+ const points = axisLabels.map((_, i) => {
11310
+ const angle = i * angleStep - Math.PI / 2;
11311
+ return {
11312
+ x: center + levelRadius * Math.cos(angle),
11313
+ y: center + levelRadius * Math.sin(angle)
11314
+ };
11315
+ });
11316
+ levelsData.push({
11317
+ path: `M ${points.map((p) => `${p.x} ${p.y}`).join(" L ")} Z`,
11318
+ level: l,
11319
+ value: l / levels * maxValue
11320
+ });
11321
+ }
11322
+ const processed = series.map((s) => {
11323
+ const points = s.data.map((d, i) => {
11324
+ const angle = i * angleStep - Math.PI / 2;
11325
+ const r = d.value / maxValue * radius;
11326
+ return {
11327
+ x: center + r * Math.cos(angle),
11328
+ y: center + r * Math.sin(angle),
11329
+ value: d.value
11330
+ };
11331
+ });
11332
+ return {
11333
+ ...s,
11334
+ points,
11335
+ path: `M ${points.map((p) => `${p.x} ${p.y}`).join(" L ")} Z`
11336
+ };
11337
+ });
11338
+ return { axes: axesData, processedSeries: processed, levelPaths: levelsData };
11339
+ }, [series, center, radius, levels]);
11340
+ return /* @__PURE__ */ jsxs46("div", { ref: containerRef, className: `relative flex flex-col gap-4 ${className}`, children: [
11341
+ /* @__PURE__ */ jsxs46("svg", { width: size, height: size, className: "overflow-visible", style: { fontFamily: "inherit" }, children: [
11342
+ /* @__PURE__ */ jsx51("g", { className: "text-muted-foreground/20", children: levelPaths.map((level, i) => /* @__PURE__ */ jsx51("path", { d: level.path, fill: "none", stroke: "currentColor", strokeWidth: 1 }, i)) }),
11343
+ /* @__PURE__ */ jsx51("g", { className: "text-muted-foreground/30", children: axes.map((axis, i) => /* @__PURE__ */ jsx51("line", { x1: center, y1: center, x2: axis.x, y2: axis.y, stroke: "currentColor", strokeWidth: 1 }, i)) }),
11344
+ processedSeries.map((s, i) => /* @__PURE__ */ jsxs46("g", { children: [
11345
+ /* @__PURE__ */ jsx51(
11346
+ "path",
11347
+ {
11348
+ d: s.path,
11349
+ fill: s.color,
11350
+ fillOpacity: s.fillOpacity ?? 0.2,
11351
+ stroke: s.color,
11352
+ strokeWidth: 2,
11353
+ strokeLinejoin: "round",
11354
+ className: "transition-all duration-300",
11355
+ style: animated ? {
11356
+ opacity: 0,
11357
+ transform: "scale(0)",
11358
+ transformOrigin: `${center}px ${center}px`,
11359
+ animation: `radarPop 0.5s ease-out ${i * 0.15}s forwards`
11360
+ } : void 0
11361
+ }
11362
+ ),
11363
+ s.points.map((point, j) => /* @__PURE__ */ jsxs46(
11364
+ "g",
11365
+ {
11366
+ onMouseEnter: () => {
11367
+ const items = processedSeries.map((ps) => ({
11368
+ label: ps.name,
11369
+ value: ps.points[j]?.value ?? 0,
11370
+ color: ps.color
11371
+ }));
11372
+ setHoveredPoint({
11373
+ x: point.x,
11374
+ y: point.y,
11375
+ axis: series[0]?.data[j]?.axis ?? "",
11376
+ items
11377
+ });
11378
+ },
11379
+ onMouseLeave: () => setHoveredPoint(null),
11380
+ className: "cursor-pointer",
11381
+ children: [
11382
+ /* @__PURE__ */ jsx51(
11383
+ "circle",
11384
+ {
11385
+ cx: point.x,
11386
+ cy: point.y,
11387
+ r: hoveredPoint?.axis === series[0]?.data[j]?.axis ? 6 : 4,
11388
+ fill: s.color,
11389
+ className: "transition-all duration-150",
11390
+ style: animated ? {
11391
+ opacity: 0,
11392
+ transform: "scale(0)",
11393
+ transformOrigin: `${point.x}px ${point.y}px`,
11394
+ animation: `dotPop 0.3s ease-out ${i * 0.15 + j * 0.05 + 0.3}s forwards`
11395
+ } : void 0
11396
+ }
11397
+ ),
11398
+ /* @__PURE__ */ jsx51("circle", { cx: point.x, cy: point.y, r: 12, fill: "transparent" })
11399
+ ]
11400
+ },
11401
+ j
11402
+ )),
11403
+ showValues && s.points.map((point, j) => /* @__PURE__ */ jsx51(
11404
+ "text",
11405
+ {
11406
+ x: point.x,
11407
+ y: point.y - 10,
11408
+ textAnchor: "middle",
11409
+ fontSize: "10",
11410
+ fontWeight: "500",
11411
+ className: "text-foreground",
11412
+ fill: "currentColor",
11413
+ style: animated ? { opacity: 0, animation: `fadeIn 0.3s ease-out ${i * 0.15 + 0.5}s forwards` } : void 0,
11414
+ children: point.value
11415
+ },
11416
+ `val-${j}`
11417
+ ))
11418
+ ] }, i)),
11419
+ showLabels && /* @__PURE__ */ jsx51("g", { className: "text-muted-foreground", children: axes.map((axis, i) => /* @__PURE__ */ jsx51("text", { x: axis.labelX, y: axis.labelY, textAnchor: "middle", dominantBaseline: "middle", fontSize: "11", fill: "currentColor", children: axis.label }, i)) }),
11420
+ /* @__PURE__ */ jsx51("style", { children: `
11421
+ @keyframes radarPop {
11422
+ from {
11423
+ opacity: 0;
11424
+ transform: scale(0);
11425
+ }
11426
+ to {
11427
+ opacity: 1;
11428
+ transform: scale(1);
11429
+ }
11430
+ }
11431
+ @keyframes dotPop {
11432
+ from {
11433
+ transform: scale(0);
11434
+ opacity: 0;
11435
+ }
11436
+ to {
11437
+ transform: scale(1);
11438
+ opacity: 1;
11439
+ }
11440
+ }
11441
+ @keyframes fadeIn {
11442
+ from { opacity: 0; }
11443
+ to { opacity: 1; }
11444
+ }
11445
+ ` })
11446
+ ] }),
11447
+ showLegend && /* @__PURE__ */ jsx51("div", { className: "flex items-center justify-center gap-6", children: series.map((s, i) => /* @__PURE__ */ jsxs46(
11448
+ "div",
11449
+ {
11450
+ className: "flex items-center gap-2 text-sm",
11451
+ style: animated ? { opacity: 0, animation: `fadeIn 0.3s ease-out ${i * 0.1 + 0.5}s forwards` } : void 0,
11452
+ children: [
11453
+ /* @__PURE__ */ jsx51("div", { className: "w-3 h-3 rounded-sm", style: { backgroundColor: s.color } }),
11454
+ /* @__PURE__ */ jsx51("span", { className: "text-muted-foreground", children: s.name })
11455
+ ]
11456
+ },
11457
+ i
11458
+ )) }),
11459
+ /* @__PURE__ */ jsx51(
11460
+ ChartTooltip,
11461
+ {
11462
+ x: hoveredPoint?.x ?? 0,
11463
+ y: hoveredPoint?.y ?? 0,
11464
+ visible: !!hoveredPoint,
11465
+ label: hoveredPoint?.axis,
11466
+ items: hoveredPoint?.items,
11467
+ containerRef
11468
+ }
11469
+ )
11470
+ ] });
11471
+ }
11472
+
11473
+ // ../../components/ui/GaugeChart.tsx
11474
+ import { useMemo as useMemo12 } from "react";
11475
+ import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
11476
+ function GaugeChart({
11477
+ value,
11478
+ min = 0,
11479
+ max = 100,
11480
+ size = 200,
11481
+ thickness = 20,
11482
+ color = "currentColor",
11483
+ backgroundColor,
11484
+ showValue = true,
11485
+ showMinMax = true,
11486
+ label,
11487
+ animated = true,
11488
+ startAngle = -135,
11489
+ endAngle = 135,
11490
+ className = ""
11491
+ }) {
11492
+ const center = size / 2;
11493
+ const radius = center - thickness / 2 - 10;
11494
+ const { backgroundPath, valuePath, percentage, needleAngle } = useMemo12(() => {
11495
+ const normalizedValue = Math.min(Math.max(value, min), max);
11496
+ const pct = (normalizedValue - min) / (max - min);
11497
+ const totalAngle = endAngle - startAngle;
11498
+ const currentAngle = startAngle + pct * totalAngle;
11499
+ const polarToCartesian = (angle) => {
11500
+ const radians = angle * Math.PI / 180;
11501
+ return {
11502
+ x: center + radius * Math.cos(radians),
11503
+ y: center + radius * Math.sin(radians)
11504
+ };
11505
+ };
11506
+ const createArc = (start, end) => {
11507
+ const startPoint = polarToCartesian(start);
11508
+ const endPoint = polarToCartesian(end);
11509
+ const largeArc = Math.abs(end - start) > 180 ? 1 : 0;
11510
+ return `M ${startPoint.x} ${startPoint.y} A ${radius} ${radius} 0 ${largeArc} 1 ${endPoint.x} ${endPoint.y}`;
11511
+ };
11512
+ return {
11513
+ backgroundPath: createArc(startAngle, endAngle),
11514
+ valuePath: createArc(startAngle, currentAngle),
11515
+ percentage: pct,
11516
+ needleAngle: currentAngle
11517
+ };
11518
+ }, [value, min, max, center, radius, startAngle, endAngle]);
11519
+ const needleLength = radius - 10;
11520
+ const needleAngleRad = needleAngle * Math.PI / 180;
11521
+ const needleX = center + needleLength * Math.cos(needleAngleRad);
11522
+ const needleY = center + needleLength * Math.sin(needleAngleRad);
11523
+ return /* @__PURE__ */ jsxs47("svg", { width: size, height: size * 0.7, className: `overflow-visible ${className}`, style: { fontFamily: "inherit" }, children: [
11524
+ /* @__PURE__ */ jsx52(
11525
+ "path",
11526
+ {
11527
+ d: backgroundPath,
11528
+ fill: "none",
11529
+ stroke: backgroundColor || "currentColor",
11530
+ strokeWidth: thickness,
11531
+ strokeLinecap: "round",
11532
+ className: !backgroundColor ? "text-muted-foreground/20" : ""
11533
+ }
11534
+ ),
11535
+ /* @__PURE__ */ jsx52(
11536
+ "path",
11537
+ {
11538
+ d: valuePath,
11539
+ fill: "none",
11540
+ stroke: color,
11541
+ strokeWidth: thickness,
11542
+ strokeLinecap: "round",
11543
+ style: animated ? {
11544
+ strokeDasharray: "1000",
11545
+ strokeDashoffset: 1e3,
11546
+ animation: "drawArc 1s ease-out forwards"
11547
+ } : void 0
11548
+ }
11549
+ ),
11550
+ /* @__PURE__ */ jsxs47(
11551
+ "g",
11552
+ {
11553
+ style: animated ? {
11554
+ transform: `rotate(${startAngle}deg)`,
11555
+ transformOrigin: `${center}px ${center}px`,
11556
+ animation: `needleRotate 1s ease-out forwards`,
11557
+ ["--needle-end"]: `${needleAngle}deg`
11558
+ } : {
11559
+ transform: `rotate(${needleAngle}deg)`,
11560
+ transformOrigin: `${center}px ${center}px`
11561
+ },
11562
+ children: [
11563
+ /* @__PURE__ */ jsx52("line", { x1: center, y1: center, x2: center + needleLength, y2: center, stroke: color, strokeWidth: 3, strokeLinecap: "round" }),
11564
+ /* @__PURE__ */ jsx52("circle", { cx: center, cy: center, r: 8, fill: color }),
11565
+ /* @__PURE__ */ jsx52("circle", { cx: center, cy: center, r: 4, className: "text-background", fill: "currentColor" })
11566
+ ]
11567
+ }
11568
+ ),
11569
+ showMinMax && /* @__PURE__ */ jsxs47("g", { className: "text-muted-foreground", children: [
11570
+ /* @__PURE__ */ jsx52(
11571
+ "text",
11572
+ {
11573
+ x: center + (radius + 20) * Math.cos(startAngle * Math.PI / 180),
11574
+ y: center + (radius + 20) * Math.sin(startAngle * Math.PI / 180) + 5,
11575
+ textAnchor: "middle",
11576
+ fontSize: "10",
11577
+ fill: "currentColor",
11578
+ children: min
11579
+ }
11580
+ ),
11581
+ /* @__PURE__ */ jsx52(
11582
+ "text",
11583
+ {
11584
+ x: center + (radius + 20) * Math.cos(endAngle * Math.PI / 180),
11585
+ y: center + (radius + 20) * Math.sin(endAngle * Math.PI / 180) + 5,
11586
+ textAnchor: "middle",
11587
+ fontSize: "10",
11588
+ fill: "currentColor",
11589
+ children: max
11590
+ }
11591
+ )
11592
+ ] }),
11593
+ showValue && /* @__PURE__ */ jsxs47("g", { children: [
11594
+ /* @__PURE__ */ jsx52(
11595
+ "text",
11596
+ {
11597
+ x: center,
11598
+ y: center + 35,
11599
+ textAnchor: "middle",
11600
+ fontSize: "24",
11601
+ fontWeight: "600",
11602
+ className: "text-foreground",
11603
+ fill: "currentColor",
11604
+ style: animated ? { opacity: 0, animation: "fadeIn 0.5s ease-out 0.5s forwards" } : void 0,
11605
+ children: value
11606
+ }
11607
+ ),
11608
+ label && /* @__PURE__ */ jsx52(
11609
+ "text",
11610
+ {
11611
+ x: center,
11612
+ y: center + 55,
11613
+ textAnchor: "middle",
11614
+ fontSize: "12",
11615
+ className: "text-muted-foreground",
11616
+ fill: "currentColor",
11617
+ style: animated ? { opacity: 0, animation: "fadeIn 0.5s ease-out 0.6s forwards" } : void 0,
11618
+ children: label
11619
+ }
11620
+ )
11621
+ ] }),
11622
+ /* @__PURE__ */ jsx52("style", { children: `
11623
+ @keyframes drawArc {
11624
+ to {
11625
+ stroke-dashoffset: 0;
11626
+ }
11627
+ }
11628
+ @keyframes needleRotate {
11629
+ to {
11630
+ transform: rotate(var(--needle-end));
11631
+ }
11632
+ }
11633
+ @keyframes fadeIn {
11634
+ from { opacity: 0; }
11635
+ to { opacity: 1; }
11636
+ }
11637
+ ` })
11638
+ ] });
11639
+ }
11640
+
11641
+ // ../../components/ui/ClientOnly.tsx
11642
+ import { useEffect as useEffect19, useState as useState38 } from "react";
11643
+ import { Fragment as Fragment19, jsx as jsx53 } from "react/jsx-runtime";
11644
+ function ClientOnly({ children, fallback = null }) {
11645
+ const [hasMounted, setHasMounted] = useState38(false);
11646
+ useEffect19(() => {
10283
11647
  setHasMounted(true);
10284
11648
  }, []);
10285
11649
  if (!hasMounted) {
10286
- return /* @__PURE__ */ jsx45(Fragment16, { children: fallback });
11650
+ return /* @__PURE__ */ jsx53(Fragment19, { children: fallback });
10287
11651
  }
10288
- return /* @__PURE__ */ jsx45(Fragment16, { children });
11652
+ return /* @__PURE__ */ jsx53(Fragment19, { children });
10289
11653
  }
10290
11654
 
10291
11655
  // ../../components/ui/Loading.tsx
10292
11656
  import { Activity as Activity3 } from "lucide-react";
10293
- import { jsx as jsx46, jsxs as jsxs40 } from "react/jsx-runtime";
11657
+ import { jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
10294
11658
  var LoadingSpinner = ({
10295
11659
  size = "md",
10296
11660
  className,
@@ -10306,7 +11670,7 @@ var LoadingSpinner = ({
10306
11670
  foreground: "text-foreground",
10307
11671
  muted: "text-muted-foreground"
10308
11672
  };
10309
- return /* @__PURE__ */ jsx46(
11673
+ return /* @__PURE__ */ jsx54(
10310
11674
  Activity3,
10311
11675
  {
10312
11676
  className: cn(
@@ -10327,7 +11691,7 @@ var LoadingDots = ({
10327
11691
  foreground: "bg-foreground",
10328
11692
  muted: "bg-muted-foreground"
10329
11693
  };
10330
- return /* @__PURE__ */ jsx46("div", { className: cn("flex items-center space-x-1", className), children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx46(
11694
+ return /* @__PURE__ */ jsx54("div", { className: cn("flex items-center space-x-1", className), children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx54(
10331
11695
  "div",
10332
11696
  {
10333
11697
  className: cn(
@@ -10349,7 +11713,7 @@ var LoadingBar = ({
10349
11713
  label
10350
11714
  }) => {
10351
11715
  const pct = progress ? Math.min(Math.max(progress, 0), 100) : void 0;
10352
- return /* @__PURE__ */ jsx46(
11716
+ return /* @__PURE__ */ jsx54(
10353
11717
  "div",
10354
11718
  {
10355
11719
  className: cn("w-full bg-muted rounded-full h-2", className),
@@ -10358,7 +11722,7 @@ var LoadingBar = ({
10358
11722
  "aria-valuemax": pct === void 0 ? void 0 : 100,
10359
11723
  "aria-valuenow": pct === void 0 ? void 0 : Math.round(pct),
10360
11724
  "aria-label": label || "Loading",
10361
- children: /* @__PURE__ */ jsx46(
11725
+ children: /* @__PURE__ */ jsx54(
10362
11726
  "div",
10363
11727
  {
10364
11728
  className: cn(
@@ -10375,9 +11739,9 @@ var LoadingBar = ({
10375
11739
  };
10376
11740
 
10377
11741
  // ../../components/ui/Table.tsx
10378
- import React38 from "react";
10379
- import { jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
10380
- var Table = React38.forwardRef(({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ jsx47(
11742
+ import React46 from "react";
11743
+ import { jsx as jsx55, jsxs as jsxs49 } from "react/jsx-runtime";
11744
+ var Table = React46.forwardRef(({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ jsx55(
10381
11745
  "div",
10382
11746
  {
10383
11747
  className: cn(
@@ -10387,20 +11751,20 @@ var Table = React38.forwardRef(({ className, containerClassName, ...props }, ref
10387
11751
  "backdrop-blur-sm transition-all duration-300",
10388
11752
  containerClassName
10389
11753
  ),
10390
- children: /* @__PURE__ */ jsx47("table", { ref, className: cn("w-full caption-bottom text-sm", className), ...props })
11754
+ children: /* @__PURE__ */ jsx55("table", { ref, className: cn("w-full caption-bottom text-sm", className), ...props })
10391
11755
  }
10392
11756
  ));
10393
11757
  Table.displayName = "Table";
10394
- var TableHeader = React38.forwardRef(({ className, children, filterRow, ...props }, ref) => /* @__PURE__ */ jsxs41("thead", { ref, className: cn("[&_tr]:border-b [&_tr]:border-border", "bg-muted/50", className), ...props, children: [
11758
+ var TableHeader = React46.forwardRef(({ className, children, filterRow, ...props }, ref) => /* @__PURE__ */ jsxs49("thead", { ref, className: cn("[&_tr]:border-b [&_tr]:border-border", "bg-muted/50", className), ...props, children: [
10395
11759
  children,
10396
11760
  filterRow
10397
11761
  ] }));
10398
11762
  TableHeader.displayName = "TableHeader";
10399
- var TableBody = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx47("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
11763
+ var TableBody = React46.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
10400
11764
  TableBody.displayName = "TableBody";
10401
- var TableFooter = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx47("tfoot", { ref, className: cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className), ...props }));
11765
+ var TableFooter = React46.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55("tfoot", { ref, className: cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className), ...props }));
10402
11766
  TableFooter.displayName = "TableFooter";
10403
- var TableRow = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx47(
11767
+ var TableRow = React46.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
10404
11768
  "tr",
10405
11769
  {
10406
11770
  ref,
@@ -10414,7 +11778,7 @@ var TableRow = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE__
10414
11778
  }
10415
11779
  ));
10416
11780
  TableRow.displayName = "TableRow";
10417
- var TableHead = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx47(
11781
+ var TableHead = React46.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
10418
11782
  "th",
10419
11783
  {
10420
11784
  ref,
@@ -10423,18 +11787,18 @@ var TableHead = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE_
10423
11787
  }
10424
11788
  ));
10425
11789
  TableHead.displayName = "TableHead";
10426
- var TableCell = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx47("td", { ref, className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className), ...props }));
11790
+ var TableCell = React46.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55("td", { ref, className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className), ...props }));
10427
11791
  TableCell.displayName = "TableCell";
10428
- var TableCaption = React38.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx47("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props }));
11792
+ var TableCaption = React46.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props }));
10429
11793
  TableCaption.displayName = "TableCaption";
10430
11794
 
10431
11795
  // ../../components/ui/DataTable.tsx
10432
11796
  import { Filter as FilterIcon } from "lucide-react";
10433
- import React39 from "react";
10434
- import { Fragment as Fragment17, jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
11797
+ import React47 from "react";
11798
+ import { Fragment as Fragment20, jsx as jsx56, jsxs as jsxs50 } from "react/jsx-runtime";
10435
11799
  function useDebounced(value, delay = 300) {
10436
- const [debounced, setDebounced] = React39.useState(value);
10437
- React39.useEffect(() => {
11800
+ const [debounced, setDebounced] = React47.useState(value);
11801
+ React47.useEffect(() => {
10438
11802
  const id = setTimeout(() => setDebounced(value), delay);
10439
11803
  return () => clearTimeout(id);
10440
11804
  }, [value, delay]);
@@ -10463,15 +11827,15 @@ function DataTable({
10463
11827
  labels
10464
11828
  }) {
10465
11829
  const t = useTranslations("Common");
10466
- const [headerAlign, setHeaderAlign] = React39.useState("left");
10467
- const [visibleCols, setVisibleCols] = React39.useState(() => columns.filter((c) => c.visible !== false).map((c) => c.key));
10468
- const [filters, setFilters] = React39.useState({});
10469
- const [sort, setSort] = React39.useState(null);
10470
- const [density, setDensity] = React39.useState("normal");
10471
- const [curPage, setCurPage] = React39.useState(page);
10472
- const hasMounted = React39.useRef(false);
10473
- const loadedFromStorage = React39.useRef(false);
10474
- const getInitialPageSize = React39.useCallback(() => {
11830
+ const [headerAlign, setHeaderAlign] = React47.useState("left");
11831
+ const [visibleCols, setVisibleCols] = React47.useState(() => columns.filter((c) => c.visible !== false).map((c) => c.key));
11832
+ const [filters, setFilters] = React47.useState({});
11833
+ const [sort, setSort] = React47.useState(null);
11834
+ const [density, setDensity] = React47.useState("normal");
11835
+ const [curPage, setCurPage] = React47.useState(page);
11836
+ const hasMounted = React47.useRef(false);
11837
+ const loadedFromStorage = React47.useRef(false);
11838
+ const getInitialPageSize = React47.useCallback(() => {
10475
11839
  if (typeof window === "undefined" || !storageKey) return pageSize;
10476
11840
  try {
10477
11841
  const saved = localStorage.getItem(`datatable_${storageKey}_pageSize`);
@@ -10486,8 +11850,8 @@ function DataTable({
10486
11850
  }
10487
11851
  return pageSize;
10488
11852
  }, [storageKey, pageSize]);
10489
- const [curPageSize, setCurPageSize] = React39.useState(getInitialPageSize);
10490
- React39.useEffect(() => {
11853
+ const [curPageSize, setCurPageSize] = React47.useState(getInitialPageSize);
11854
+ React47.useEffect(() => {
10491
11855
  if (typeof window === "undefined" || !storageKey) return;
10492
11856
  if (!hasMounted.current) return;
10493
11857
  try {
@@ -10495,7 +11859,7 @@ function DataTable({
10495
11859
  } catch {
10496
11860
  }
10497
11861
  }, [curPageSize, storageKey]);
10498
- React39.useEffect(() => {
11862
+ React47.useEffect(() => {
10499
11863
  const newColKeys = columns.filter((c) => c.visible !== false).map((c) => c.key);
10500
11864
  setVisibleCols((prev) => {
10501
11865
  const uniqueKeys = /* @__PURE__ */ new Set([...prev, ...newColKeys]);
@@ -10503,16 +11867,16 @@ function DataTable({
10503
11867
  });
10504
11868
  }, [columns]);
10505
11869
  const debouncedFilters = useDebounced(filters, 350);
10506
- React39.useEffect(() => {
11870
+ React47.useEffect(() => {
10507
11871
  setCurPage(page);
10508
11872
  }, [page]);
10509
- React39.useEffect(() => {
11873
+ React47.useEffect(() => {
10510
11874
  if (storageKey && loadedFromStorage.current) {
10511
11875
  return;
10512
11876
  }
10513
11877
  setCurPageSize(pageSize);
10514
11878
  }, [pageSize, storageKey]);
10515
- React39.useEffect(() => {
11879
+ React47.useEffect(() => {
10516
11880
  if (!onQueryChange) return;
10517
11881
  if (!hasMounted.current) {
10518
11882
  hasMounted.current = true;
@@ -10535,7 +11899,7 @@ function DataTable({
10535
11899
  className: "h-8 w-full text-sm"
10536
11900
  };
10537
11901
  if (col.filter.type === "text") {
10538
- return /* @__PURE__ */ jsx48(
11902
+ return /* @__PURE__ */ jsx56(
10539
11903
  Input_default,
10540
11904
  {
10541
11905
  ...commonProps,
@@ -10550,7 +11914,7 @@ function DataTable({
10550
11914
  }
10551
11915
  if (col.filter.type === "select") {
10552
11916
  const options = col.filter.options || [];
10553
- return /* @__PURE__ */ jsx48(
11917
+ return /* @__PURE__ */ jsx56(
10554
11918
  Combobox,
10555
11919
  {
10556
11920
  options: ["", ...options],
@@ -10566,7 +11930,7 @@ function DataTable({
10566
11930
  );
10567
11931
  }
10568
11932
  if (col.filter.type === "date") {
10569
- return /* @__PURE__ */ jsx48(
11933
+ return /* @__PURE__ */ jsx56(
10570
11934
  DatePicker,
10571
11935
  {
10572
11936
  placeholder: col.filter.placeholder || `Select ${String(col.title)}`,
@@ -10580,7 +11944,7 @@ function DataTable({
10580
11944
  }
10581
11945
  return null;
10582
11946
  };
10583
- const renderHeader = /* @__PURE__ */ jsx48(TableRow, { children: visibleColumns.map((col, colIdx) => /* @__PURE__ */ jsx48(
11947
+ const renderHeader = /* @__PURE__ */ jsx56(TableRow, { children: visibleColumns.map((col, colIdx) => /* @__PURE__ */ jsx56(
10584
11948
  TableHead,
10585
11949
  {
10586
11950
  style: { width: col.width },
@@ -10593,9 +11957,9 @@ function DataTable({
10593
11957
  children: (() => {
10594
11958
  const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
10595
11959
  const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
10596
- const titleContent = /* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-1 min-w-0 shrink", children: [
10597
- /* @__PURE__ */ jsx48("span", { className: "truncate font-medium text-sm", children: col.title }),
10598
- col.sortable && /* @__PURE__ */ jsx48(
11960
+ const titleContent = /* @__PURE__ */ jsxs50("div", { className: "flex items-center gap-1 min-w-0 shrink", children: [
11961
+ /* @__PURE__ */ jsx56("span", { className: "truncate font-medium text-sm", children: col.title }),
11962
+ col.sortable && /* @__PURE__ */ jsx56(
10599
11963
  "button",
10600
11964
  {
10601
11965
  className: cn(
@@ -10612,8 +11976,8 @@ function DataTable({
10612
11976
  },
10613
11977
  "aria-label": "Sort",
10614
11978
  title: `Sort by ${String(col.title)}`,
10615
- children: /* @__PURE__ */ jsxs42("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
10616
- /* @__PURE__ */ jsx48(
11979
+ children: /* @__PURE__ */ jsxs50("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
11980
+ /* @__PURE__ */ jsx56(
10617
11981
  "path",
10618
11982
  {
10619
11983
  d: "M7 8l3-3 3 3",
@@ -10624,7 +11988,7 @@ function DataTable({
10624
11988
  opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
10625
11989
  }
10626
11990
  ),
10627
- /* @__PURE__ */ jsx48(
11991
+ /* @__PURE__ */ jsx56(
10628
11992
  "path",
10629
11993
  {
10630
11994
  d: "M7 12l3 3 3-3",
@@ -10639,11 +12003,11 @@ function DataTable({
10639
12003
  }
10640
12004
  )
10641
12005
  ] });
10642
- const filterContent = col.filter && /* @__PURE__ */ jsx48(
12006
+ const filterContent = col.filter && /* @__PURE__ */ jsx56(
10643
12007
  Popover,
10644
12008
  {
10645
12009
  placement: isRightAlign ? "bottom-end" : "bottom-start",
10646
- trigger: /* @__PURE__ */ jsx48(
12010
+ trigger: /* @__PURE__ */ jsx56(
10647
12011
  "button",
10648
12012
  {
10649
12013
  className: cn(
@@ -10653,16 +12017,16 @@ function DataTable({
10653
12017
  ),
10654
12018
  "aria-label": "Filter",
10655
12019
  title: "Filter",
10656
- children: /* @__PURE__ */ jsx48(FilterIcon, { className: "h-4 w-4" })
12020
+ children: /* @__PURE__ */ jsx56(FilterIcon, { className: "h-4 w-4" })
10657
12021
  }
10658
12022
  ),
10659
- children: /* @__PURE__ */ jsxs42("div", { className: "w-48 p-2 space-y-2", children: [
10660
- /* @__PURE__ */ jsxs42("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: [
12023
+ children: /* @__PURE__ */ jsxs50("div", { className: "w-48 p-2 space-y-2", children: [
12024
+ /* @__PURE__ */ jsxs50("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: [
10661
12025
  "Filter ",
10662
12026
  col.title
10663
12027
  ] }),
10664
12028
  renderFilterControl(col),
10665
- filters[col.key] && /* @__PURE__ */ jsx48(
12029
+ filters[col.key] && /* @__PURE__ */ jsx56(
10666
12030
  "button",
10667
12031
  {
10668
12032
  onClick: () => {
@@ -10680,7 +12044,7 @@ function DataTable({
10680
12044
  ] })
10681
12045
  }
10682
12046
  );
10683
- return /* @__PURE__ */ jsx48(
12047
+ return /* @__PURE__ */ jsx56(
10684
12048
  "div",
10685
12049
  {
10686
12050
  className: cn(
@@ -10689,10 +12053,10 @@ function DataTable({
10689
12053
  isCenterAlign && "justify-center",
10690
12054
  !isRightAlign && !isCenterAlign && "justify-between"
10691
12055
  ),
10692
- children: isRightAlign ? /* @__PURE__ */ jsxs42(Fragment17, { children: [
12056
+ children: isRightAlign ? /* @__PURE__ */ jsxs50(Fragment20, { children: [
10693
12057
  filterContent,
10694
12058
  titleContent
10695
- ] }) : /* @__PURE__ */ jsxs42(Fragment17, { children: [
12059
+ ] }) : /* @__PURE__ */ jsxs50(Fragment20, { children: [
10696
12060
  titleContent,
10697
12061
  filterContent
10698
12062
  ] })
@@ -10703,7 +12067,7 @@ function DataTable({
10703
12067
  col.key
10704
12068
  )) });
10705
12069
  const isServerMode = Boolean(onQueryChange);
10706
- const processedData = React39.useMemo(() => {
12070
+ const processedData = React47.useMemo(() => {
10707
12071
  if (isServerMode) return data;
10708
12072
  let result = [...data];
10709
12073
  if (Object.keys(filters).length > 0) {
@@ -10735,21 +12099,21 @@ function DataTable({
10735
12099
  return result;
10736
12100
  }, [data, isServerMode, filters, sort, columns]);
10737
12101
  const totalItems = isServerMode ? total : processedData.length;
10738
- const displayedData = isServerMode ? data : React39.useMemo(() => {
12102
+ const displayedData = isServerMode ? data : React47.useMemo(() => {
10739
12103
  const start = (curPage - 1) * curPageSize;
10740
12104
  if (start >= processedData.length && curPage > 1) {
10741
12105
  }
10742
12106
  return processedData.slice(start, start + curPageSize);
10743
12107
  }, [processedData, curPage, curPageSize]);
10744
- return /* @__PURE__ */ jsxs42("div", { className: cn("space-y-2", className), children: [
10745
- /* @__PURE__ */ jsxs42("div", { className: "flex items-center justify-between gap-4 mb-1", children: [
10746
- /* @__PURE__ */ jsx48("div", { className: "text-sm text-muted-foreground", children: caption }),
10747
- /* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-2", children: [
10748
- enableDensityToggle && /* @__PURE__ */ jsx48(
12108
+ return /* @__PURE__ */ jsxs50("div", { className: cn("space-y-2", className), children: [
12109
+ /* @__PURE__ */ jsxs50("div", { className: "flex items-center justify-between gap-4 mb-1", children: [
12110
+ /* @__PURE__ */ jsx56("div", { className: "text-sm text-muted-foreground", children: caption }),
12111
+ /* @__PURE__ */ jsxs50("div", { className: "flex items-center gap-2", children: [
12112
+ enableDensityToggle && /* @__PURE__ */ jsx56(
10749
12113
  DropdownMenu_default,
10750
12114
  {
10751
- trigger: /* @__PURE__ */ jsxs42(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
10752
- /* @__PURE__ */ jsx48("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx48("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
12115
+ trigger: /* @__PURE__ */ jsxs50(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
12116
+ /* @__PURE__ */ jsx56("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx56("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
10753
12117
  labels?.density || t("density")
10754
12118
  ] }),
10755
12119
  items: [
@@ -10759,11 +12123,11 @@ function DataTable({
10759
12123
  ]
10760
12124
  }
10761
12125
  ),
10762
- enableColumnVisibilityToggle && /* @__PURE__ */ jsx48(
12126
+ enableColumnVisibilityToggle && /* @__PURE__ */ jsx56(
10763
12127
  DropdownMenu_default,
10764
12128
  {
10765
- trigger: /* @__PURE__ */ jsxs42(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
10766
- /* @__PURE__ */ jsx48("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx48(
12129
+ trigger: /* @__PURE__ */ jsxs50(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
12130
+ /* @__PURE__ */ jsx56("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx56(
10767
12131
  "path",
10768
12132
  {
10769
12133
  strokeLinecap: "round",
@@ -10774,26 +12138,26 @@ function DataTable({
10774
12138
  ) }),
10775
12139
  labels?.columns || t("columns")
10776
12140
  ] }),
10777
- children: columns.map((c) => /* @__PURE__ */ jsxs42(
12141
+ children: columns.map((c) => /* @__PURE__ */ jsxs50(
10778
12142
  DropdownMenuItem,
10779
12143
  {
10780
12144
  onClick: () => {
10781
12145
  setVisibleCols((prev) => prev.includes(c.key) ? prev.filter((k) => k !== c.key) : [...prev, c.key]);
10782
12146
  },
10783
12147
  children: [
10784
- /* @__PURE__ */ jsx48("input", { type: "checkbox", className: "mr-2 rounded border-border", readOnly: true, checked: visibleCols.includes(c.key) }),
10785
- /* @__PURE__ */ jsx48("span", { className: "truncate", children: c.title })
12148
+ /* @__PURE__ */ jsx56("input", { type: "checkbox", className: "mr-2 rounded border-border", readOnly: true, checked: visibleCols.includes(c.key) }),
12149
+ /* @__PURE__ */ jsx56("span", { className: "truncate", children: c.title })
10786
12150
  ]
10787
12151
  },
10788
12152
  c.key
10789
12153
  ))
10790
12154
  }
10791
12155
  ),
10792
- enableHeaderAlignToggle && /* @__PURE__ */ jsx48(
12156
+ enableHeaderAlignToggle && /* @__PURE__ */ jsx56(
10793
12157
  DropdownMenu_default,
10794
12158
  {
10795
- trigger: /* @__PURE__ */ jsxs42(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
10796
- /* @__PURE__ */ jsx48("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx48("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h10M4 18h16" }) }),
12159
+ trigger: /* @__PURE__ */ jsxs50(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
12160
+ /* @__PURE__ */ jsx56("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx56("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h10M4 18h16" }) }),
10797
12161
  labels?.headerAlign || t("headerAlign")
10798
12162
  ] }),
10799
12163
  items: [
@@ -10806,17 +12170,17 @@ function DataTable({
10806
12170
  toolbar
10807
12171
  ] })
10808
12172
  ] }),
10809
- /* @__PURE__ */ jsx48("div", { className: cn("relative rounded-md border border-border/50 overflow-hidden", loading2 && "opacity-60 pointer-events-none"), children: /* @__PURE__ */ jsxs42(
12173
+ /* @__PURE__ */ jsx56("div", { className: cn("relative rounded-md border border-border/50 overflow-hidden", loading2 && "opacity-60 pointer-events-none"), children: /* @__PURE__ */ jsxs50(
10810
12174
  Table,
10811
12175
  {
10812
12176
  containerClassName: "border-0 md:border-0 rounded-none md:rounded-none shadow-none bg-transparent",
10813
12177
  className: "[&_thead]:sticky [&_thead]:top-0 [&_thead]:z-5 [&_thead]:bg-background [&_thead]:backdrop-blur-sm",
10814
12178
  children: [
10815
- /* @__PURE__ */ jsx48(TableHeader, { children: renderHeader }),
10816
- /* @__PURE__ */ jsx48(TableBody, { children: loading2 ? /* @__PURE__ */ jsx48(TableRow, { children: /* @__PURE__ */ jsx48(TableCell, { colSpan: visibleColumns.length, className: "text-center py-8", children: /* @__PURE__ */ jsxs42("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
10817
- /* @__PURE__ */ jsxs42("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
10818
- /* @__PURE__ */ jsx48("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
10819
- /* @__PURE__ */ jsx48(
12179
+ /* @__PURE__ */ jsx56(TableHeader, { children: renderHeader }),
12180
+ /* @__PURE__ */ jsx56(TableBody, { children: loading2 ? /* @__PURE__ */ jsx56(TableRow, { children: /* @__PURE__ */ jsx56(TableCell, { colSpan: visibleColumns.length, className: "text-center py-8", children: /* @__PURE__ */ jsxs50("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
12181
+ /* @__PURE__ */ jsxs50("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
12182
+ /* @__PURE__ */ jsx56("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
12183
+ /* @__PURE__ */ jsx56(
10820
12184
  "path",
10821
12185
  {
10822
12186
  className: "opacity-75",
@@ -10825,12 +12189,12 @@ function DataTable({
10825
12189
  }
10826
12190
  )
10827
12191
  ] }),
10828
- /* @__PURE__ */ jsx48("span", { className: "text-sm", children: "Loading..." })
10829
- ] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ jsx48(TableRow, { children: /* @__PURE__ */ jsx48(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: "No data" }) }) : displayedData.map((row, idx) => {
12192
+ /* @__PURE__ */ jsx56("span", { className: "text-sm", children: "Loading..." })
12193
+ ] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ jsx56(TableRow, { children: /* @__PURE__ */ jsx56(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: "No data" }) }) : displayedData.map((row, idx) => {
10830
12194
  const isLastRow = idx === displayedData.length - 1;
10831
- return /* @__PURE__ */ jsx48(TableRow, { className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/50"), children: visibleColumns.map((col, colIdx) => {
12195
+ return /* @__PURE__ */ jsx56(TableRow, { className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/50"), children: visibleColumns.map((col, colIdx) => {
10832
12196
  const value = col.dataIndex ? row[col.dataIndex] : void 0;
10833
- return /* @__PURE__ */ jsx48(
12197
+ return /* @__PURE__ */ jsx56(
10834
12198
  TableCell,
10835
12199
  {
10836
12200
  className: cn(
@@ -10850,7 +12214,7 @@ function DataTable({
10850
12214
  ]
10851
12215
  }
10852
12216
  ) }),
10853
- totalItems > 0 && /* @__PURE__ */ jsx48("div", { className: "border-t bg-muted/30 p-4 rounded-b-md", children: /* @__PURE__ */ jsx48(
12217
+ totalItems > 0 && /* @__PURE__ */ jsx56("div", { className: "border-t bg-muted/30 p-4 rounded-b-md", children: /* @__PURE__ */ jsx56(
10854
12218
  Pagination,
10855
12219
  {
10856
12220
  page: curPage,
@@ -10872,10 +12236,10 @@ function DataTable({
10872
12236
  var DataTable_default = DataTable;
10873
12237
 
10874
12238
  // ../../components/ui/Form.tsx
10875
- import * as React40 from "react";
12239
+ import * as React48 from "react";
10876
12240
  import { Controller, FormProvider, useFormContext, useForm } from "react-hook-form";
10877
- import { jsx as jsx49, jsxs as jsxs43 } from "react/jsx-runtime";
10878
- var FormConfigContext = React40.createContext({ size: "md" });
12241
+ import { jsx as jsx57, jsxs as jsxs51 } from "react/jsx-runtime";
12242
+ var FormConfigContext = React48.createContext({ size: "md" });
10879
12243
  var FormWrapper = ({
10880
12244
  children,
10881
12245
  onSubmit,
@@ -10888,24 +12252,24 @@ var FormWrapper = ({
10888
12252
  const methods = useForm({
10889
12253
  defaultValues: initialValues
10890
12254
  });
10891
- React40.useEffect(() => {
12255
+ React48.useEffect(() => {
10892
12256
  if (initialValues) {
10893
12257
  methods.reset(initialValues);
10894
12258
  }
10895
12259
  }, [JSON.stringify(initialValues)]);
10896
12260
  const { validationSchema: _, ...formProps } = props;
10897
- return /* @__PURE__ */ jsx49(FormProvider, { ...methods, children: /* @__PURE__ */ jsx49(FormConfigContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx49("form", { onSubmit: methods.handleSubmit(onSubmit), className, ...formProps, children }) }) });
12261
+ return /* @__PURE__ */ jsx57(FormProvider, { ...methods, children: /* @__PURE__ */ jsx57(FormConfigContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx57("form", { onSubmit: methods.handleSubmit(onSubmit), className, ...formProps, children }) }) });
10898
12262
  };
10899
12263
  var Form = FormWrapper;
10900
- var FormFieldContext = React40.createContext({});
12264
+ var FormFieldContext = React48.createContext({});
10901
12265
  var FormField = ({
10902
12266
  ...props
10903
12267
  }) => {
10904
- return /* @__PURE__ */ jsx49(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx49(Controller, { ...props }) });
12268
+ return /* @__PURE__ */ jsx57(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx57(Controller, { ...props }) });
10905
12269
  };
10906
12270
  var useFormField = () => {
10907
- const fieldContext = React40.useContext(FormFieldContext);
10908
- const itemContext = React40.useContext(FormItemContext);
12271
+ const fieldContext = React48.useContext(FormFieldContext);
12272
+ const itemContext = React48.useContext(FormItemContext);
10909
12273
  const { getFieldState, formState } = useFormContext();
10910
12274
  if (!fieldContext) {
10911
12275
  try {
@@ -10926,27 +12290,27 @@ var useFormField = () => {
10926
12290
  ...fieldState
10927
12291
  };
10928
12292
  };
10929
- var FormItemContext = React40.createContext({});
10930
- var FormItem = React40.forwardRef(({ className, ...props }, ref) => {
10931
- const id = React40.useId();
10932
- return /* @__PURE__ */ jsx49(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx49("div", { ref, className: cn("space-y-2", className), ...props }) });
12293
+ var FormItemContext = React48.createContext({});
12294
+ var FormItem = React48.forwardRef(({ className, ...props }, ref) => {
12295
+ const id = React48.useId();
12296
+ return /* @__PURE__ */ jsx57(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx57("div", { ref, className: cn("space-y-2", className), ...props }) });
10933
12297
  });
10934
12298
  FormItem.displayName = "FormItem";
10935
- var FormLabel = React40.forwardRef(
12299
+ var FormLabel = React48.forwardRef(
10936
12300
  ({ className, children, required, ...props }, ref) => {
10937
12301
  const { error, formItemId } = useFormField();
10938
- const config = React40.useContext(FormConfigContext);
12302
+ const config = React48.useContext(FormConfigContext);
10939
12303
  const sizeClass = config.size === "sm" ? "text-xs" : config.size === "lg" ? "text-base" : "text-sm";
10940
- return /* @__PURE__ */ jsxs43(Label, { ref, className: cn(sizeClass, error && "text-destructive", className), htmlFor: formItemId, ...props, children: [
12304
+ return /* @__PURE__ */ jsxs51(Label, { ref, className: cn(sizeClass, error && "text-destructive", className), htmlFor: formItemId, ...props, children: [
10941
12305
  children,
10942
- required && /* @__PURE__ */ jsx49("span", { className: "text-destructive ml-1", children: "*" })
12306
+ required && /* @__PURE__ */ jsx57("span", { className: "text-destructive ml-1", children: "*" })
10943
12307
  ] });
10944
12308
  }
10945
12309
  );
10946
12310
  FormLabel.displayName = "FormLabel";
10947
- var FormControl = React40.forwardRef(({ ...props }, ref) => {
12311
+ var FormControl = React48.forwardRef(({ ...props }, ref) => {
10948
12312
  const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
10949
- return /* @__PURE__ */ jsx49(
12313
+ return /* @__PURE__ */ jsx57(
10950
12314
  "div",
10951
12315
  {
10952
12316
  ref,
@@ -10958,37 +12322,37 @@ var FormControl = React40.forwardRef(({ ...props }, ref) => {
10958
12322
  );
10959
12323
  });
10960
12324
  FormControl.displayName = "FormControl";
10961
- var FormDescription = React40.forwardRef(({ className, ...props }, ref) => {
12325
+ var FormDescription = React48.forwardRef(({ className, ...props }, ref) => {
10962
12326
  const { formDescriptionId } = useFormField();
10963
- return /* @__PURE__ */ jsx49("p", { ref, id: formDescriptionId, className: cn("text-sm text-muted-foreground", className), ...props });
12327
+ return /* @__PURE__ */ jsx57("p", { ref, id: formDescriptionId, className: cn("text-sm text-muted-foreground", className), ...props });
10964
12328
  });
10965
12329
  FormDescription.displayName = "FormDescription";
10966
- var FormMessage = React40.forwardRef(({ className, children, ...props }, ref) => {
12330
+ var FormMessage = React48.forwardRef(({ className, children, ...props }, ref) => {
10967
12331
  const { error, formMessageId } = useFormField();
10968
12332
  const body = error ? String(error?.message) : children;
10969
12333
  if (!body) {
10970
12334
  return null;
10971
12335
  }
10972
- return /* @__PURE__ */ jsx49("p", { ref, id: formMessageId, className: cn("text-sm font-medium text-destructive", className), ...props, children: body });
12336
+ return /* @__PURE__ */ jsx57("p", { ref, id: formMessageId, className: cn("text-sm font-medium text-destructive", className), ...props, children: body });
10973
12337
  });
10974
12338
  FormMessage.displayName = "FormMessage";
10975
- var FormInput = React40.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx49(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx49(
12339
+ var FormInput = React48.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx57(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx57(
10976
12340
  FormField,
10977
12341
  {
10978
12342
  name,
10979
- render: ({ field }) => /* @__PURE__ */ jsxs43(FormItem, { children: [
10980
- /* @__PURE__ */ jsx49(FormControl, { children: /* @__PURE__ */ jsx49(Input_default, { size: props.size ?? size, ...field, ...props }) }),
10981
- /* @__PURE__ */ jsx49(FormMessage, {})
12343
+ render: ({ field }) => /* @__PURE__ */ jsxs51(FormItem, { children: [
12344
+ /* @__PURE__ */ jsx57(FormControl, { children: /* @__PURE__ */ jsx57(Input_default, { size: props.size ?? size, ...field, ...props }) }),
12345
+ /* @__PURE__ */ jsx57(FormMessage, {})
10982
12346
  ] })
10983
12347
  }
10984
12348
  ) }));
10985
12349
  FormInput.displayName = "FormInput";
10986
- var FormCheckbox = React40.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx49(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx49(
12350
+ var FormCheckbox = React48.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ jsx57(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx57(
10987
12351
  FormField,
10988
12352
  {
10989
12353
  name,
10990
- render: ({ field }) => /* @__PURE__ */ jsxs43(FormItem, { children: [
10991
- /* @__PURE__ */ jsx49(FormControl, { children: /* @__PURE__ */ jsx49(
12354
+ render: ({ field }) => /* @__PURE__ */ jsxs51(FormItem, { children: [
12355
+ /* @__PURE__ */ jsx57(FormControl, { children: /* @__PURE__ */ jsx57(
10992
12356
  Checkbox,
10993
12357
  {
10994
12358
  ref,
@@ -11002,21 +12366,21 @@ var FormCheckbox = React40.forwardRef(({ name, ...props }, ref) => /* @__PURE__
11002
12366
  ...props
11003
12367
  }
11004
12368
  ) }),
11005
- /* @__PURE__ */ jsx49(FormMessage, {})
12369
+ /* @__PURE__ */ jsx57(FormMessage, {})
11006
12370
  ] })
11007
12371
  }
11008
12372
  ) }));
11009
12373
  FormCheckbox.displayName = "FormCheckbox";
11010
- var FormActions = React40.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx49("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
12374
+ var FormActions = React48.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx57("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
11011
12375
  FormActions.displayName = "FormActions";
11012
- var FormSubmitButton = React40.forwardRef(
11013
- ({ children, loading: loading2, ...props }, ref) => /* @__PURE__ */ jsx49(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx49(Button_default, { ref, type: "submit", size: props.size ?? size, disabled: loading2, ...props, children }) })
12376
+ var FormSubmitButton = React48.forwardRef(
12377
+ ({ children, loading: loading2, ...props }, ref) => /* @__PURE__ */ jsx57(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ jsx57(Button_default, { ref, type: "submit", size: props.size ?? size, disabled: loading2, ...props, children }) })
11014
12378
  );
11015
12379
  FormSubmitButton.displayName = "FormSubmitButton";
11016
12380
 
11017
12381
  // ../../components/ui/NotificationModal.tsx
11018
12382
  import { ExternalLink } from "lucide-react";
11019
- import { jsx as jsx50, jsxs as jsxs44 } from "react/jsx-runtime";
12383
+ import { jsx as jsx58, jsxs as jsxs52 } from "react/jsx-runtime";
11020
12384
  function NotificationModal({ isOpen, onClose, notification, titleText, openLinkText, closeText }) {
11021
12385
  const t = useTranslations("Common");
11022
12386
  if (!notification) return null;
@@ -11037,20 +12401,20 @@ function NotificationModal({ isOpen, onClose, notification, titleText, openLinkT
11037
12401
  onClose();
11038
12402
  }
11039
12403
  };
11040
- return /* @__PURE__ */ jsx50(Modal_default, { isOpen, onClose, title: titleText || t("notifications"), size: "md", children: /* @__PURE__ */ jsxs44("div", { className: "space-y-4", children: [
11041
- /* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2 pb-2 border-b border-border", children: [
11042
- /* @__PURE__ */ jsx50("div", { className: cn("w-2 h-2 rounded-full", !notification.is_read ? "bg-primary" : "bg-border") }),
11043
- /* @__PURE__ */ jsx50("span", { className: "text-xs text-muted-foreground", children: !notification.is_read ? t("newNotification") : t("readStatus") })
12404
+ return /* @__PURE__ */ jsx58(Modal_default, { isOpen, onClose, title: titleText || t("notifications"), size: "md", children: /* @__PURE__ */ jsxs52("div", { className: "space-y-4", children: [
12405
+ /* @__PURE__ */ jsxs52("div", { className: "flex items-center gap-2 pb-2 border-b border-border", children: [
12406
+ /* @__PURE__ */ jsx58("div", { className: cn("w-2 h-2 rounded-full", !notification.is_read ? "bg-primary" : "bg-border") }),
12407
+ /* @__PURE__ */ jsx58("span", { className: "text-xs text-muted-foreground", children: !notification.is_read ? t("newNotification") : t("readStatus") })
11044
12408
  ] }),
11045
- notification.title && /* @__PURE__ */ jsx50("h3", { className: "text-lg font-semibold text-foreground", children: notification.title }),
11046
- notification.body && /* @__PURE__ */ jsx50("div", { className: "text-sm text-muted-foreground whitespace-pre-wrap leading-relaxed", children: notification.body }),
11047
- /* @__PURE__ */ jsx50("div", { className: "text-xs text-muted-foreground border-t border-border pt-2", children: formatTime3(notification.created_at) }),
11048
- /* @__PURE__ */ jsxs44("div", { className: "flex gap-2 justify-end pt-2", children: [
11049
- hasLink && /* @__PURE__ */ jsxs44(Button_default, { variant: "primary", size: "sm", onClick: handleLinkClick, className: "gap-2", children: [
11050
- /* @__PURE__ */ jsx50(ExternalLink, { className: "w-4 h-4" }),
12409
+ notification.title && /* @__PURE__ */ jsx58("h3", { className: "text-lg font-semibold text-foreground", children: notification.title }),
12410
+ notification.body && /* @__PURE__ */ jsx58("div", { className: "text-sm text-muted-foreground whitespace-pre-wrap leading-relaxed", children: notification.body }),
12411
+ /* @__PURE__ */ jsx58("div", { className: "text-xs text-muted-foreground border-t border-border pt-2", children: formatTime3(notification.created_at) }),
12412
+ /* @__PURE__ */ jsxs52("div", { className: "flex gap-2 justify-end pt-2", children: [
12413
+ hasLink && /* @__PURE__ */ jsxs52(Button_default, { variant: "primary", size: "sm", onClick: handleLinkClick, className: "gap-2", children: [
12414
+ /* @__PURE__ */ jsx58(ExternalLink, { className: "w-4 h-4" }),
11051
12415
  openLinkText || t("openLink")
11052
12416
  ] }),
11053
- /* @__PURE__ */ jsx50(Button_default, { variant: "ghost", size: "sm", onClick: onClose, children: closeText || t("close") })
12417
+ /* @__PURE__ */ jsx58(Button_default, { variant: "ghost", size: "sm", onClick: onClose, children: closeText || t("close") })
11054
12418
  ] })
11055
12419
  ] }) });
11056
12420
  }
@@ -11060,9 +12424,9 @@ var NotificationModal_default = NotificationModal;
11060
12424
  import Link2 from "next/link";
11061
12425
  import { usePathname } from "next/navigation";
11062
12426
  import { Phone } from "lucide-react";
11063
- import { jsx as jsx51, jsxs as jsxs45 } from "react/jsx-runtime";
12427
+ import { jsx as jsx59, jsxs as jsxs53 } from "react/jsx-runtime";
11064
12428
  function MessengerIcon(props) {
11065
- return /* @__PURE__ */ jsx51("svg", { viewBox: "0 0 24 24", width: 24, height: 24, "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx51(
12429
+ return /* @__PURE__ */ jsx59("svg", { viewBox: "0 0 24 24", width: 24, height: 24, "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx59(
11066
12430
  "path",
11067
12431
  {
11068
12432
  d: "M12 2C6.477 2 2 6.145 2 11.235c0 2.93 1.35 5.542 3.464 7.25v3.515l3.344-1.836c.894.247 1.843.375 2.192.375 5.523 0 10-4.145 10-9.235S17.523 2 12 2zm.994 12.444l-2.563-2.73-5.004 2.73 5.507-5.84 2.626 2.729 4.942-2.729-5.508 5.84z",
@@ -11071,7 +12435,7 @@ function MessengerIcon(props) {
11071
12435
  ) });
11072
12436
  }
11073
12437
  function ZaloIcon(props) {
11074
- return /* @__PURE__ */ jsx51("svg", { viewBox: "0 0 48 48", width: 20, height: 20, "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx51(
12438
+ return /* @__PURE__ */ jsx59("svg", { viewBox: "0 0 48 48", width: 20, height: 20, "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx59(
11075
12439
  "path",
11076
12440
  {
11077
12441
  fill: "white",
@@ -11080,7 +12444,7 @@ function ZaloIcon(props) {
11080
12444
  ) });
11081
12445
  }
11082
12446
  function InstagramIcon(props) {
11083
- return /* @__PURE__ */ jsx51("svg", { viewBox: "0 0 24 24", width: 20, height: 20, "aria-hidden": "true", fill: "white", ...props, children: /* @__PURE__ */ jsx51("path", { d: "M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" }) });
12447
+ return /* @__PURE__ */ jsx59("svg", { viewBox: "0 0 24 24", width: 20, height: 20, "aria-hidden": "true", fill: "white", ...props, children: /* @__PURE__ */ jsx59("path", { d: "M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" }) });
11084
12448
  }
11085
12449
  function FloatingContacts({ className }) {
11086
12450
  const pathname = usePathname();
@@ -11115,8 +12479,8 @@ function FloatingContacts({ className }) {
11115
12479
  external: true
11116
12480
  }
11117
12481
  ];
11118
- return /* @__PURE__ */ jsxs45("div", { className: cn("fixed bottom-6 right-4 z-100000", "flex flex-col items-end gap-3", className), "aria-label": "Quick contacts", children: [
11119
- /* @__PURE__ */ jsx51(
12482
+ return /* @__PURE__ */ jsxs53("div", { className: cn("fixed bottom-6 right-4 z-100000", "flex flex-col items-end gap-3", className), "aria-label": "Quick contacts", children: [
12483
+ /* @__PURE__ */ jsx59(
11120
12484
  Link2,
11121
12485
  {
11122
12486
  href: `tel:${hotline.replace(/\D/g, "")}`,
@@ -11127,10 +12491,10 @@ function FloatingContacts({ className }) {
11127
12491
  "hover:scale-105 active:scale-95 transition-transform",
11128
12492
  "bg-[#22c55e]"
11129
12493
  ),
11130
- children: /* @__PURE__ */ jsx51(Phone, { className: "w-6 h-6" })
12494
+ children: /* @__PURE__ */ jsx59(Phone, { className: "w-6 h-6" })
11131
12495
  }
11132
12496
  ),
11133
- moreItems.map(({ key, href, label, bg, Icon, external }) => /* @__PURE__ */ jsx51(
12497
+ moreItems.map(({ key, href, label, bg, Icon, external }) => /* @__PURE__ */ jsx59(
11134
12498
  Link2,
11135
12499
  {
11136
12500
  href,
@@ -11142,7 +12506,7 @@ function FloatingContacts({ className }) {
11142
12506
  "hover:scale-105 active:scale-95 transition-transform",
11143
12507
  bg
11144
12508
  ),
11145
- children: /* @__PURE__ */ jsx51(Icon, { className: "w-6 h-6" })
12509
+ children: /* @__PURE__ */ jsx59(Icon, { className: "w-6 h-6" })
11146
12510
  },
11147
12511
  key
11148
12512
  ))
@@ -11151,7 +12515,7 @@ function FloatingContacts({ className }) {
11151
12515
 
11152
12516
  // ../../components/ui/AccessDenied.tsx
11153
12517
  import { Ban, Lock, ShieldAlert } from "lucide-react";
11154
- import { jsx as jsx52, jsxs as jsxs46 } from "react/jsx-runtime";
12518
+ import { jsx as jsx60, jsxs as jsxs54 } from "react/jsx-runtime";
11155
12519
  var VARIANT_STYLES = {
11156
12520
  destructive: { bg: "bg-destructive/5", border: "border-destructive/20", text: "text-destructive" },
11157
12521
  warning: { bg: "bg-warning/5", border: "border-warning/20", text: "text-warning" },
@@ -11172,32 +12536,32 @@ function AccessDenied({
11172
12536
  }) {
11173
12537
  const styles = VARIANT_STYLES[variant];
11174
12538
  const UsedIcon = Icon || DEFAULT_ICONS[variant];
11175
- return /* @__PURE__ */ jsx52(Card_default, { className: cn("p-8 text-center shadow-sm", styles.bg, styles.border, className), children: /* @__PURE__ */ jsxs46("div", { className: "flex flex-col items-center gap-4", children: [
11176
- /* @__PURE__ */ jsx52("div", { className: cn("p-3 rounded-lg", styles.bg.replace("/5", "/10")), children: /* @__PURE__ */ jsx52(UsedIcon, { className: cn("w-8 h-8", styles.text) }) }),
11177
- /* @__PURE__ */ jsxs46("div", { children: [
11178
- /* @__PURE__ */ jsx52("h3", { className: cn("font-semibold mb-2", styles.text), children: title }),
11179
- /* @__PURE__ */ jsx52("p", { className: cn(styles.text.replace("text-", "text-") + "/80", "text-sm"), children: description })
12539
+ return /* @__PURE__ */ jsx60(Card_default, { className: cn("p-8 text-center shadow-sm", styles.bg, styles.border, className), children: /* @__PURE__ */ jsxs54("div", { className: "flex flex-col items-center gap-4", children: [
12540
+ /* @__PURE__ */ jsx60("div", { className: cn("p-3 rounded-lg", styles.bg.replace("/5", "/10")), children: /* @__PURE__ */ jsx60(UsedIcon, { className: cn("w-8 h-8", styles.text) }) }),
12541
+ /* @__PURE__ */ jsxs54("div", { children: [
12542
+ /* @__PURE__ */ jsx60("h3", { className: cn("font-semibold mb-2", styles.text), children: title }),
12543
+ /* @__PURE__ */ jsx60("p", { className: cn(styles.text.replace("text-", "text-") + "/80", "text-sm"), children: description })
11180
12544
  ] }),
11181
- children && /* @__PURE__ */ jsx52("div", { className: "mt-2 flex flex-wrap gap-2 justify-center", children })
12545
+ children && /* @__PURE__ */ jsx60("div", { className: "mt-2 flex flex-wrap gap-2 justify-center", children })
11182
12546
  ] }) });
11183
12547
  }
11184
12548
 
11185
12549
  // ../../components/ui/ThemeToggleHeadless.tsx
11186
12550
  import { Moon, Sun, Monitor } from "lucide-react";
11187
- import { useEffect as useEffect20, useRef as useRef14, useState as useState33 } from "react";
11188
- import { createPortal as createPortal10 } from "react-dom";
11189
- import { Fragment as Fragment18, jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
12551
+ import { useEffect as useEffect21, useRef as useRef19, useState as useState39 } from "react";
12552
+ import { createPortal as createPortal11 } from "react-dom";
12553
+ import { Fragment as Fragment21, jsx as jsx61, jsxs as jsxs55 } from "react/jsx-runtime";
11190
12554
  function ThemeToggleHeadless({
11191
12555
  theme,
11192
12556
  onChange,
11193
12557
  labels,
11194
12558
  className
11195
12559
  }) {
11196
- const [isOpen, setIsOpen] = useState33(false);
11197
- const [mounted, setMounted] = useState33(false);
11198
- const triggerRef = useRef14(null);
11199
- const [dropdownPosition, setDropdownPosition] = useState33(null);
11200
- useEffect20(() => setMounted(true), []);
12560
+ const [isOpen, setIsOpen] = useState39(false);
12561
+ const [mounted, setMounted] = useState39(false);
12562
+ const triggerRef = useRef19(null);
12563
+ const [dropdownPosition, setDropdownPosition] = useState39(null);
12564
+ useEffect21(() => setMounted(true), []);
11201
12565
  const themes = [
11202
12566
  { value: "light", label: labels?.light ?? "Light", icon: Sun },
11203
12567
  { value: "dark", label: labels?.dark ?? "Dark", icon: Moon },
@@ -11215,8 +12579,8 @@ function ThemeToggleHeadless({
11215
12579
  const top = rect.bottom + scrollTop + 8;
11216
12580
  return { top, left, width };
11217
12581
  };
11218
- return /* @__PURE__ */ jsxs47("div", { className: cn("relative", className), children: [
11219
- /* @__PURE__ */ jsx53(
12582
+ return /* @__PURE__ */ jsxs55("div", { className: cn("relative", className), children: [
12583
+ /* @__PURE__ */ jsx61(
11220
12584
  Button_default,
11221
12585
  {
11222
12586
  variant: "ghost",
@@ -11234,25 +12598,25 @@ function ThemeToggleHeadless({
11234
12598
  "aria-haspopup": "menu",
11235
12599
  "aria-expanded": isOpen,
11236
12600
  "aria-label": labels?.heading ?? "Theme",
11237
- children: /* @__PURE__ */ jsx53(CurrentIcon, { className: "h-5 w-5" })
12601
+ children: /* @__PURE__ */ jsx61(CurrentIcon, { className: "h-5 w-5" })
11238
12602
  }
11239
12603
  ),
11240
- isOpen && /* @__PURE__ */ jsxs47(Fragment18, { children: [
11241
- typeof window !== "undefined" && createPortal10(/* @__PURE__ */ jsx53("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
11242
- typeof window !== "undefined" && dropdownPosition && createPortal10(
11243
- /* @__PURE__ */ jsx53(
12604
+ isOpen && /* @__PURE__ */ jsxs55(Fragment21, { children: [
12605
+ typeof window !== "undefined" && createPortal11(/* @__PURE__ */ jsx61("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
12606
+ typeof window !== "undefined" && dropdownPosition && createPortal11(
12607
+ /* @__PURE__ */ jsx61(
11244
12608
  "div",
11245
12609
  {
11246
12610
  className: "z-9999 bg-card border border-border rounded-lg shadow-lg overflow-hidden",
11247
12611
  style: { position: "absolute", top: dropdownPosition.top, left: dropdownPosition.left, width: dropdownPosition.width },
11248
12612
  onMouseDown: (e) => e.stopPropagation(),
11249
12613
  role: "menu",
11250
- children: /* @__PURE__ */ jsxs47("div", { className: "p-2", children: [
11251
- /* @__PURE__ */ jsx53("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Theme" }),
12614
+ children: /* @__PURE__ */ jsxs55("div", { className: "p-2", children: [
12615
+ /* @__PURE__ */ jsx61("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Theme" }),
11252
12616
  themes.map((opt) => {
11253
12617
  const Icon = opt.icon;
11254
12618
  const active = theme === opt.value;
11255
- return /* @__PURE__ */ jsxs47(
12619
+ return /* @__PURE__ */ jsxs55(
11256
12620
  Button_default,
11257
12621
  {
11258
12622
  variant: "ghost",
@@ -11268,9 +12632,9 @@ function ThemeToggleHeadless({
11268
12632
  role: "menuitemradio",
11269
12633
  "aria-checked": active,
11270
12634
  children: [
11271
- /* @__PURE__ */ jsx53(Icon, { className: "h-4 w-4" }),
11272
- /* @__PURE__ */ jsx53("span", { className: "flex-1 text-left", children: opt.label }),
11273
- active && /* @__PURE__ */ jsx53("div", { className: "w-2 h-2 rounded-full bg-primary" })
12635
+ /* @__PURE__ */ jsx61(Icon, { className: "h-4 w-4" }),
12636
+ /* @__PURE__ */ jsx61("span", { className: "flex-1 text-left", children: opt.label }),
12637
+ active && /* @__PURE__ */ jsx61("div", { className: "w-2 h-2 rounded-full bg-primary" })
11274
12638
  ]
11275
12639
  },
11276
12640
  opt.value
@@ -11286,10 +12650,10 @@ function ThemeToggleHeadless({
11286
12650
  }
11287
12651
 
11288
12652
  // ../../components/ui/LanguageSwitcherHeadless.tsx
11289
- import { useRef as useRef15, useState as useState34 } from "react";
11290
- import { createPortal as createPortal11 } from "react-dom";
12653
+ import { useRef as useRef20, useState as useState40 } from "react";
12654
+ import { createPortal as createPortal12 } from "react-dom";
11291
12655
  import { Globe } from "lucide-react";
11292
- import { Fragment as Fragment19, jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
12656
+ import { Fragment as Fragment22, jsx as jsx62, jsxs as jsxs56 } from "react/jsx-runtime";
11293
12657
  function LanguageSwitcherHeadless({
11294
12658
  locales,
11295
12659
  currentLocale,
@@ -11297,9 +12661,9 @@ function LanguageSwitcherHeadless({
11297
12661
  labels,
11298
12662
  className
11299
12663
  }) {
11300
- const [isOpen, setIsOpen] = useState34(false);
11301
- const [dropdownPosition, setDropdownPosition] = useState34(null);
11302
- const triggerButtonRef = useRef15(null);
12664
+ const [isOpen, setIsOpen] = useState40(false);
12665
+ const [dropdownPosition, setDropdownPosition] = useState40(null);
12666
+ const triggerButtonRef = useRef20(null);
11303
12667
  const currentLanguage = locales.find((l) => l.code === currentLocale) || locales[0];
11304
12668
  const calculatePosition = () => {
11305
12669
  const rect = triggerButtonRef.current?.getBoundingClientRect();
@@ -11311,8 +12675,8 @@ function LanguageSwitcherHeadless({
11311
12675
  const top = rect.bottom + scrollTop + 8;
11312
12676
  return { top, left, width };
11313
12677
  };
11314
- return /* @__PURE__ */ jsxs48("div", { className: cn("relative", className), children: [
11315
- /* @__PURE__ */ jsx54(
12678
+ return /* @__PURE__ */ jsxs56("div", { className: cn("relative", className), children: [
12679
+ /* @__PURE__ */ jsx62(
11316
12680
  Button_default,
11317
12681
  {
11318
12682
  variant: "ghost",
@@ -11331,22 +12695,22 @@ function LanguageSwitcherHeadless({
11331
12695
  "aria-expanded": isOpen,
11332
12696
  "aria-label": labels?.heading ?? "Language",
11333
12697
  title: labels?.heading ?? "Language",
11334
- children: /* @__PURE__ */ jsx54(Globe, { className: "h-5 w-5" })
12698
+ children: /* @__PURE__ */ jsx62(Globe, { className: "h-5 w-5" })
11335
12699
  }
11336
12700
  ),
11337
- isOpen && /* @__PURE__ */ jsxs48(Fragment19, { children: [
11338
- typeof window !== "undefined" && createPortal11(/* @__PURE__ */ jsx54("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
11339
- typeof window !== "undefined" && dropdownPosition && createPortal11(
11340
- /* @__PURE__ */ jsx54(
12701
+ isOpen && /* @__PURE__ */ jsxs56(Fragment22, { children: [
12702
+ typeof window !== "undefined" && createPortal12(/* @__PURE__ */ jsx62("div", { className: "fixed inset-0 z-9998", onClick: () => setIsOpen(false) }), document.body),
12703
+ typeof window !== "undefined" && dropdownPosition && createPortal12(
12704
+ /* @__PURE__ */ jsx62(
11341
12705
  "div",
11342
12706
  {
11343
12707
  className: "z-9999 bg-card border border-border rounded-lg shadow-lg overflow-hidden",
11344
12708
  style: { position: "absolute", top: dropdownPosition.top, left: dropdownPosition.left, width: dropdownPosition.width },
11345
12709
  onMouseDown: (e) => e.stopPropagation(),
11346
12710
  role: "menu",
11347
- children: /* @__PURE__ */ jsxs48("div", { className: "p-2", children: [
11348
- /* @__PURE__ */ jsx54("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Language" }),
11349
- locales.map((language) => /* @__PURE__ */ jsxs48(
12711
+ children: /* @__PURE__ */ jsxs56("div", { className: "p-2", children: [
12712
+ /* @__PURE__ */ jsx62("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Language" }),
12713
+ locales.map((language) => /* @__PURE__ */ jsxs56(
11350
12714
  Button_default,
11351
12715
  {
11352
12716
  variant: "ghost",
@@ -11359,9 +12723,9 @@ function LanguageSwitcherHeadless({
11359
12723
  role: "menuitemradio",
11360
12724
  "aria-checked": currentLocale === language.code,
11361
12725
  children: [
11362
- language.flag && /* @__PURE__ */ jsx54("span", { className: "text-lg", children: language.flag }),
11363
- /* @__PURE__ */ jsx54("span", { className: "flex-1 text-left", children: language.name }),
11364
- currentLocale === language.code && /* @__PURE__ */ jsx54("div", { className: "w-2 h-2 rounded-full bg-primary" })
12726
+ language.flag && /* @__PURE__ */ jsx62("span", { className: "text-lg", children: language.flag }),
12727
+ /* @__PURE__ */ jsx62("span", { className: "flex-1 text-left", children: language.name }),
12728
+ currentLocale === language.code && /* @__PURE__ */ jsx62("div", { className: "w-2 h-2 rounded-full bg-primary" })
11365
12729
  ]
11366
12730
  },
11367
12731
  language.code
@@ -11791,7 +13155,7 @@ var VARIANT_STYLES_ALERT = {
11791
13155
  };
11792
13156
 
11793
13157
  // src/contexts/TranslationContext.tsx
11794
- import * as React42 from "react";
13158
+ import * as React50 from "react";
11795
13159
 
11796
13160
  // locales/en.json
11797
13161
  var en_default = {
@@ -12046,16 +13410,16 @@ var ja_default = {
12046
13410
  };
12047
13411
 
12048
13412
  // src/contexts/TranslationContext.tsx
12049
- import { jsx as jsx55 } from "react/jsx-runtime";
13413
+ import { jsx as jsx63 } from "react/jsx-runtime";
12050
13414
  var defaultTranslations2 = {
12051
13415
  en: en_default,
12052
13416
  vi: vi_default,
12053
13417
  ko: ko_default,
12054
13418
  ja: ja_default
12055
13419
  };
12056
- var TranslationContext2 = React42.createContext(null);
13420
+ var TranslationContext2 = React50.createContext(null);
12057
13421
  var TranslationProvider = ({ children, locale = "en", translations }) => {
12058
- const t = React42.useCallback(
13422
+ const t = React50.useCallback(
12059
13423
  (namespace) => {
12060
13424
  return (key) => {
12061
13425
  const mergedTranslations = {
@@ -12080,10 +13444,10 @@ var TranslationProvider = ({ children, locale = "en", translations }) => {
12080
13444
  },
12081
13445
  [locale, translations]
12082
13446
  );
12083
- return /* @__PURE__ */ jsx55(TranslationContext2.Provider, { value: { locale, t }, children });
13447
+ return /* @__PURE__ */ jsx63(TranslationContext2.Provider, { value: { locale, t }, children });
12084
13448
  };
12085
13449
  var useUnderverseTranslations = (namespace) => {
12086
- const context = React42.useContext(TranslationContext2);
13450
+ const context = React50.useContext(TranslationContext2);
12087
13451
  if (!context) {
12088
13452
  return (key) => {
12089
13453
  const parts = namespace.split(".");
@@ -12105,13 +13469,13 @@ var useUnderverseTranslations = (namespace) => {
12105
13469
  return context.t(namespace);
12106
13470
  };
12107
13471
  var useUnderverseLocale = () => {
12108
- const context = React42.useContext(TranslationContext2);
13472
+ const context = React50.useContext(TranslationContext2);
12109
13473
  return context?.locale || "en";
12110
13474
  };
12111
13475
 
12112
13476
  // src/hooks/useSmartTranslations.tsx
12113
- import * as React43 from "react";
12114
- import { jsx as jsx56 } from "react/jsx-runtime";
13477
+ import * as React51 from "react";
13478
+ import { jsx as jsx64 } from "react/jsx-runtime";
12115
13479
  var nextIntlHooks = null;
12116
13480
  try {
12117
13481
  const nextIntl = __require("next-intl");
@@ -12122,12 +13486,12 @@ try {
12122
13486
  } catch {
12123
13487
  nextIntlHooks = null;
12124
13488
  }
12125
- var ForceInternalContext = React43.createContext(false);
13489
+ var ForceInternalContext = React51.createContext(false);
12126
13490
  var ForceInternalTranslationsProvider = ({ children }) => {
12127
- return /* @__PURE__ */ jsx56(ForceInternalContext.Provider, { value: true, children });
13491
+ return /* @__PURE__ */ jsx64(ForceInternalContext.Provider, { value: true, children });
12128
13492
  };
12129
13493
  function useSmartTranslations(namespace) {
12130
- const forceInternal = React43.useContext(ForceInternalContext);
13494
+ const forceInternal = React51.useContext(ForceInternalContext);
12131
13495
  const internalT = useUnderverseTranslations(namespace);
12132
13496
  if (forceInternal || !nextIntlHooks?.useTranslations) {
12133
13497
  return internalT;
@@ -12140,7 +13504,7 @@ function useSmartTranslations(namespace) {
12140
13504
  }
12141
13505
  }
12142
13506
  function useSmartLocale() {
12143
- const forceInternal = React43.useContext(ForceInternalContext);
13507
+ const forceInternal = React51.useContext(ForceInternalContext);
12144
13508
  const internalLocale = useUnderverseLocale();
12145
13509
  if (forceInternal || !nextIntlHooks?.useLocale) {
12146
13510
  return internalLocale;
@@ -12161,9 +13525,11 @@ function getUnderverseMessages(locale = "en") {
12161
13525
  export {
12162
13526
  AccessDenied,
12163
13527
  Alert_default as Alert,
13528
+ AreaChart,
12164
13529
  Avatar_default as Avatar,
12165
13530
  Badge_default as Badge,
12166
13531
  Badge as BadgeBase,
13532
+ BarChart,
12167
13533
  BatteryProgress,
12168
13534
  BottomSheet,
12169
13535
  Breadcrumb_default as Breadcrumb,
@@ -12201,6 +13567,7 @@ export {
12201
13567
  FormLabel,
12202
13568
  FormMessage,
12203
13569
  FormSubmitButton,
13570
+ GaugeChart,
12204
13571
  GlobalLoading,
12205
13572
  GradientBadge,
12206
13573
  Grid_default as Grid,
@@ -12212,6 +13579,7 @@ export {
12212
13579
  Label,
12213
13580
  LanguageSwitcherHeadless as LanguageSwitcher,
12214
13581
  LanguageSwitcherHeadless,
13582
+ LineChart,
12215
13583
  List_default as List,
12216
13584
  ListItem,
12217
13585
  LoadingBar,
@@ -12228,10 +13596,12 @@ export {
12228
13596
  PageLoading,
12229
13597
  Pagination,
12230
13598
  PasswordInput,
13599
+ PieChart,
12231
13600
  PillTabs,
12232
13601
  Popover,
12233
13602
  Progress,
12234
13603
  PulseBadge,
13604
+ RadarChart,
12235
13605
  RadioGroup,
12236
13606
  RadioGroupItem,
12237
13607
  SIZE_STYLES_BTN,
@@ -12256,6 +13626,7 @@ export {
12256
13626
  SlideOver,
12257
13627
  Slider,
12258
13628
  SmartImage,
13629
+ Sparkline,
12259
13630
  StatusBadge,
12260
13631
  StepProgress,
12261
13632
  Switch_default as Switch,