@marcoschwartz/lite-ui 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5300,14 +5300,32 @@ var LineChart = ({
5300
5300
  strokeWidth = 2,
5301
5301
  className = "",
5302
5302
  xAxisLabel,
5303
- yAxisLabel
5303
+ yAxisLabel,
5304
+ baseFontSize = 14
5304
5305
  }) => {
5305
- const height = providedHeight ?? 400;
5306
- const width = providedWidth ?? (responsive ? 600 : 600);
5306
+ const viewBoxWidth = 1e3;
5307
+ const viewBoxHeight = 600;
5308
+ const containerRef = import_react26.default.useRef(null);
5309
+ const svgRef = import_react26.default.useRef(null);
5310
+ const [tooltipPosition, setTooltipPosition] = import_react26.default.useState(null);
5307
5311
  const [hoveredPoint, setHoveredPoint] = import_react26.default.useState(null);
5308
- const padding = { top: 20, right: 20, bottom: showXAxis ? 60 : 20, left: showYAxis ? 60 : 20 };
5309
- const chartWidth = width - padding.left - padding.right;
5310
- const chartHeight = height - padding.top - padding.bottom;
5312
+ const chartId = import_react26.default.useId();
5313
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
5314
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
5315
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
5316
+ const lineClass = `chart-line-${chartId.replace(/:/g, "-")}`;
5317
+ const pointClass = `chart-point-${chartId.replace(/:/g, "-")}`;
5318
+ const padding = {
5319
+ top: 50,
5320
+ right: 50,
5321
+ bottom: showXAxis ? 120 : 50,
5322
+ left: showYAxis ? 130 : 50
5323
+ };
5324
+ const chartWidth = viewBoxWidth - padding.left - padding.right;
5325
+ const chartHeight = viewBoxHeight - padding.top - padding.bottom;
5326
+ const gridLabelFontSize = viewBoxWidth * 0.045;
5327
+ const axisLabelFontSize = viewBoxWidth * 0.05;
5328
+ const titleFontSize = viewBoxWidth * 0.055;
5311
5329
  const allPoints = data.flatMap((series) => series.data);
5312
5330
  const allYValues = allPoints.map((p) => p.y);
5313
5331
  const firstXValue = data[0]?.data[0]?.x;
@@ -5320,7 +5338,7 @@ var LineChart = ({
5320
5338
  const minY = Math.min(0, ...allYValues);
5321
5339
  const maxY = Math.max(...allYValues);
5322
5340
  const yRange = maxY - minY;
5323
- const yMin = minY - yRange * 0.1;
5341
+ const yMin = Math.max(0, minY - yRange * 0.1);
5324
5342
  const yMax = maxY + yRange * 0.1;
5325
5343
  const scaleX = (x, index) => {
5326
5344
  const numX = isStringX ? index : x;
@@ -5367,29 +5385,32 @@ var LineChart = ({
5367
5385
  x2: chartWidth,
5368
5386
  y2: y,
5369
5387
  stroke: "currentColor",
5370
- strokeWidth: "1",
5388
+ strokeWidth: "0.5",
5371
5389
  className: "text-gray-200 dark:text-gray-700",
5372
- strokeDasharray: "2,2"
5390
+ strokeDasharray: "4,4"
5373
5391
  }
5374
5392
  ),
5375
5393
  showYAxis && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5376
5394
  "text",
5377
5395
  {
5378
- x: -10,
5379
- y: y + 4,
5396
+ x: -25,
5397
+ y,
5380
5398
  textAnchor: "end",
5381
- fontSize: "16",
5382
- className: "fill-gray-600 dark:fill-gray-400",
5399
+ dominantBaseline: "middle",
5400
+ fontSize: gridLabelFontSize,
5401
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5383
5402
  children: yValue.toFixed(1)
5384
5403
  }
5385
5404
  )
5386
5405
  ] }, `grid-h-${i}`)
5387
5406
  );
5388
5407
  }
5389
- const numXGridLines = Math.min(allPoints.length, 6);
5408
+ const numXGridLines = Math.max(2, Math.min(allPoints.length, 6));
5409
+ const xGridStep = numXGridLines > 1 ? 1 / (numXGridLines - 1) : 0;
5390
5410
  for (let i = 0; i < numXGridLines; i++) {
5391
- const x = chartWidth / (numXGridLines - 1) * i;
5392
- const xValue = data[0]?.data[Math.floor((data[0].data.length - 1) * (i / (numXGridLines - 1)))]?.x || "";
5411
+ const x = chartWidth * (i * xGridStep);
5412
+ const dataIndex = Math.floor((data[0]?.data.length - 1) * (i * xGridStep));
5413
+ const xValue = data[0]?.data[Math.max(0, Math.min(dataIndex, data[0].data.length - 1))]?.x || "";
5393
5414
  gridLines.push(
5394
5415
  /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("g", { children: [
5395
5416
  /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
@@ -5400,19 +5421,20 @@ var LineChart = ({
5400
5421
  x2: x,
5401
5422
  y2: chartHeight,
5402
5423
  stroke: "currentColor",
5403
- strokeWidth: "1",
5424
+ strokeWidth: "0.5",
5404
5425
  className: "text-gray-200 dark:text-gray-700",
5405
- strokeDasharray: "2,2"
5426
+ strokeDasharray: "4,4"
5406
5427
  }
5407
5428
  ),
5408
5429
  showXAxis && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5409
5430
  "text",
5410
5431
  {
5411
5432
  x,
5412
- y: chartHeight + 20,
5433
+ y: chartHeight + 35,
5413
5434
  textAnchor: "middle",
5414
- fontSize: "14",
5415
- className: "fill-gray-600 dark:fill-gray-400",
5435
+ dominantBaseline: "hanging",
5436
+ fontSize: gridLabelFontSize,
5437
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5416
5438
  children: xValue
5417
5439
  }
5418
5440
  )
@@ -5420,21 +5442,74 @@ var LineChart = ({
5420
5442
  );
5421
5443
  }
5422
5444
  }
5445
+ const getTooltipPosition = import_react26.default.useCallback((x, y) => {
5446
+ if (!containerRef.current) return { x, y };
5447
+ const rect = containerRef.current.getBoundingClientRect();
5448
+ const tooltipWidth = 120;
5449
+ const tooltipHeight = 80;
5450
+ let tooltipX = x + 10;
5451
+ let tooltipY = y - 30;
5452
+ if (tooltipX + tooltipWidth > rect.width) {
5453
+ tooltipX = x - tooltipWidth - 10;
5454
+ }
5455
+ if (tooltipY + tooltipHeight > rect.height) {
5456
+ tooltipY = y + 30;
5457
+ }
5458
+ return { x: tooltipX, y: tooltipY };
5459
+ }, []);
5460
+ const containerStyle = {
5461
+ "--font-size-base": `${baseFontSize}px`,
5462
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
5463
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
5464
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`
5465
+ };
5423
5466
  return /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)(
5424
5467
  "div",
5425
5468
  {
5426
- className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
5427
- style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
5469
+ ref: containerRef,
5470
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
5471
+ style: {
5472
+ ...containerStyle
5473
+ },
5428
5474
  children: [
5475
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("style", { children: `
5476
+ /* Mobile: Large fonts, hidden axis titles, thicker lines (default) */
5477
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
5478
+ .${axisLabelClass} { display: none; }
5479
+ .${lineClass} { stroke-width: ${strokeWidth * 2.5} !important; }
5480
+ .${pointClass} { r: 6 !important; stroke-width: 3 !important; }
5481
+
5482
+ /* Tablet: Medium fonts, show axis titles, medium lines */
5483
+ @media (min-width: 640px) {
5484
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
5485
+ .${axisLabelClass} {
5486
+ font-size: ${axisLabelFontSize * 0.7}px !important;
5487
+ display: block;
5488
+ }
5489
+ .${lineClass} { stroke-width: ${strokeWidth * 1.5} !important; }
5490
+ .${pointClass} { r: 4 !important; stroke-width: 2 !important; }
5491
+ }
5492
+
5493
+ /* Desktop: Small fonts, show axis titles, normal lines */
5494
+ @media (min-width: 1024px) {
5495
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
5496
+ .${axisLabelClass} {
5497
+ font-size: ${axisLabelFontSize * 0.4}px !important;
5498
+ display: block;
5499
+ }
5500
+ .${lineClass} { stroke-width: ${strokeWidth} !important; }
5501
+ .${pointClass} { r: 3 !important; stroke-width: 1.5 !important; }
5502
+ }
5503
+ ` }),
5429
5504
  /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5430
5505
  "svg",
5431
5506
  {
5507
+ ref: svgRef,
5432
5508
  width: "100%",
5433
- height: "100%",
5434
- viewBox: `0 0 ${width} ${height}`,
5509
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
5435
5510
  preserveAspectRatio: "xMidYMid meet",
5436
- className: "bg-white dark:bg-gray-800 block",
5437
- style: { overflow: "visible" },
5511
+ className: "bg-white dark:bg-gray-800 block w-full",
5512
+ style: { height: "auto", overflow: "visible" },
5438
5513
  children: /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5439
5514
  gridLines,
5440
5515
  data.map((series, seriesIndex) => /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
@@ -5445,7 +5520,8 @@ var LineChart = ({
5445
5520
  stroke: series.color || defaultColors[seriesIndex % defaultColors.length],
5446
5521
  strokeWidth,
5447
5522
  strokeLinecap: "round",
5448
- strokeLinejoin: "round"
5523
+ strokeLinejoin: "round",
5524
+ className: lineClass
5449
5525
  },
5450
5526
  `line-${seriesIndex}`
5451
5527
  )),
@@ -5459,13 +5535,32 @@ var LineChart = ({
5459
5535
  {
5460
5536
  cx: x,
5461
5537
  cy: y,
5462
- r: isHovered ? 6 : 4,
5538
+ r: isHovered ? 5 : 3,
5463
5539
  fill: series.color || defaultColors[seriesIndex % defaultColors.length],
5464
5540
  stroke: "white",
5465
- strokeWidth: "2",
5466
- className: "cursor-pointer transition-all",
5467
- onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
5468
- onMouseLeave: () => setHoveredPoint(null)
5541
+ strokeWidth: "1.5",
5542
+ className: `cursor-pointer transition-all ${pointClass}`,
5543
+ onMouseEnter: (e) => {
5544
+ if (showTooltip && containerRef.current) {
5545
+ setHoveredPoint({ seriesIndex, pointIndex, x, y });
5546
+ const containerRect = containerRef.current.getBoundingClientRect();
5547
+ const mouseX = e.clientX - containerRect.left;
5548
+ const mouseY = e.clientY - containerRect.top;
5549
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
5550
+ }
5551
+ },
5552
+ onMouseMove: (e) => {
5553
+ if (showTooltip && hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex && containerRef.current) {
5554
+ const containerRect = containerRef.current.getBoundingClientRect();
5555
+ const mouseX = e.clientX - containerRect.left;
5556
+ const mouseY = e.clientY - containerRect.top;
5557
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
5558
+ }
5559
+ },
5560
+ onMouseLeave: () => {
5561
+ setHoveredPoint(null);
5562
+ setTooltipPosition(null);
5563
+ }
5469
5564
  },
5470
5565
  `point-${seriesIndex}-${pointIndex}`
5471
5566
  );
@@ -5475,11 +5570,12 @@ var LineChart = ({
5475
5570
  "text",
5476
5571
  {
5477
5572
  x: chartWidth / 2,
5478
- y: chartHeight + 50,
5573
+ y: chartHeight + 80,
5479
5574
  textAnchor: "middle",
5480
- fontSize: "16",
5481
- fontWeight: "500",
5482
- className: "fill-gray-700 dark:fill-gray-300",
5575
+ dominantBaseline: "hanging",
5576
+ fontSize: axisLabelFontSize,
5577
+ fontWeight: "600",
5578
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5483
5579
  children: xAxisLabel
5484
5580
  }
5485
5581
  ),
@@ -5487,45 +5583,47 @@ var LineChart = ({
5487
5583
  "text",
5488
5584
  {
5489
5585
  x: -chartHeight / 2,
5490
- y: -45,
5586
+ y: -100,
5491
5587
  textAnchor: "middle",
5492
- fontSize: "16",
5493
- fontWeight: "500",
5494
- transform: `rotate(-90, 0, 0)`,
5495
- className: "fill-gray-700 dark:fill-gray-300",
5588
+ dominantBaseline: "middle",
5589
+ fontSize: axisLabelFontSize,
5590
+ fontWeight: "600",
5591
+ transform: "rotate(-90)",
5592
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5496
5593
  children: yAxisLabel
5497
5594
  }
5498
5595
  )
5499
5596
  ] })
5500
5597
  }
5501
5598
  ),
5502
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { className: "flex items-center gap-2", children: [
5599
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { className: "flex items-center gap-2 text-sm", children: [
5503
5600
  /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5504
5601
  "div",
5505
5602
  {
5506
- className: "w-4 h-4 rounded-sm",
5603
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
5507
5604
  style: {
5508
5605
  backgroundColor: series.color || defaultColors[index % defaultColors.length]
5509
5606
  }
5510
5607
  }
5511
5608
  ),
5512
- /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5609
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("span", { className: "text-gray-700 dark:text-gray-300", children: series.name })
5513
5610
  ] }, `legend-${index}`)) }),
5514
- showTooltip && hoveredPoint && /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)(
5611
+ showTooltip && hoveredPoint && tooltipPosition && /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)(
5515
5612
  "div",
5516
5613
  {
5517
- className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50",
5614
+ className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg pointer-events-none z-50 text-sm whitespace-nowrap",
5518
5615
  style: {
5519
- left: `${padding.left + hoveredPoint.x + 10}px`,
5520
- top: `${padding.top + hoveredPoint.y - 30}px`
5616
+ left: `${tooltipPosition.x}px`,
5617
+ top: `${tooltipPosition.y}px`,
5618
+ transform: "translateZ(0)"
5521
5619
  },
5522
5620
  children: [
5523
5621
  /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
5524
- /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { children: [
5622
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { className: "text-xs opacity-90", children: [
5525
5623
  "x: ",
5526
5624
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
5527
5625
  ] }),
5528
- /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { children: [
5626
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { className: "text-xs opacity-90", children: [
5529
5627
  "y: ",
5530
5628
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
5531
5629
  ] })
@@ -5571,26 +5669,38 @@ var BarChart = ({
5571
5669
  barWidth = 0.8,
5572
5670
  className = "",
5573
5671
  xAxisLabel,
5574
- yAxisLabel
5672
+ yAxisLabel,
5673
+ baseFontSize = 14,
5674
+ colors = defaultColors2
5575
5675
  }) => {
5576
- const height = providedHeight ?? 400;
5577
- const width = providedWidth ?? (responsive ? 800 : 600);
5676
+ const viewBoxWidth = 1e3;
5677
+ const viewBoxHeight = 600;
5678
+ const containerRef = import_react27.default.useRef(null);
5679
+ const [tooltipPosition, setTooltipPosition] = import_react27.default.useState(null);
5578
5680
  const [hoveredBar, setHoveredBar] = import_react27.default.useState(null);
5681
+ const chartId = import_react27.default.useId();
5682
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
5683
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
5684
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
5685
+ const barClass = `chart-bar-${chartId.replace(/:/g, "-")}`;
5579
5686
  const padding = {
5580
- top: 20,
5581
- right: 20,
5582
- bottom: showXAxis ? horizontal ? 60 : 80 : 20,
5583
- left: showYAxis ? horizontal ? 80 : 60 : 20
5687
+ top: 50,
5688
+ right: 50,
5689
+ bottom: showXAxis ? horizontal ? 120 : 140 : 50,
5690
+ left: showYAxis ? horizontal ? 140 : 130 : 50
5584
5691
  };
5585
- const chartWidth = width - padding.left - padding.right;
5586
- const chartHeight = height - padding.top - padding.bottom;
5692
+ const chartWidth = viewBoxWidth - padding.left - padding.right;
5693
+ const chartHeight = viewBoxHeight - padding.top - padding.bottom;
5694
+ const gridLabelFontSize = viewBoxWidth * 0.045;
5695
+ const axisLabelFontSize = viewBoxWidth * 0.05;
5696
+ const titleFontSize = viewBoxWidth * 0.055;
5587
5697
  const allYValues = stacked ? data[0]?.data.map(
5588
5698
  (_, i) => data.reduce((sum, series) => sum + (series.data[i]?.y || 0), 0)
5589
5699
  ) || [] : data.flatMap((series) => series.data.map((p) => p.y));
5590
5700
  const minY = Math.min(0, ...allYValues);
5591
5701
  const maxY = Math.max(...allYValues);
5592
5702
  const yRange = maxY - minY;
5593
- const yMin = minY - yRange * 0.1;
5703
+ const yMin = Math.max(0, minY - yRange * 0.1);
5594
5704
  const yMax = maxY + yRange * 0.1;
5595
5705
  const numBars = data[0]?.data.length || 0;
5596
5706
  const numSeries = data.length;
@@ -5617,19 +5727,20 @@ var BarChart = ({
5617
5727
  x2: chartWidth,
5618
5728
  y2: y,
5619
5729
  stroke: "currentColor",
5620
- strokeWidth: "1",
5730
+ strokeWidth: "0.5",
5621
5731
  className: "text-gray-200 dark:text-gray-700",
5622
- strokeDasharray: "2,2"
5732
+ strokeDasharray: "4,4"
5623
5733
  }
5624
5734
  ),
5625
5735
  showYAxis && !horizontal && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5626
5736
  "text",
5627
5737
  {
5628
- x: -10,
5629
- y: y + 4,
5738
+ x: -25,
5739
+ y,
5630
5740
  textAnchor: "end",
5631
- fontSize: "14",
5632
- className: "fill-gray-600 dark:fill-gray-400",
5741
+ dominantBaseline: "middle",
5742
+ fontSize: gridLabelFontSize,
5743
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5633
5744
  children: yValue.toFixed(0)
5634
5745
  }
5635
5746
  )
@@ -5678,12 +5789,20 @@ var BarChart = ({
5678
5789
  x: xPos,
5679
5790
  y: yPos,
5680
5791
  width: barW,
5681
- height: barHeight,
5682
- fill: data[seriesIndex].color || defaultColors2[seriesIndex % defaultColors2.length],
5683
- className: "cursor-pointer transition-opacity",
5792
+ height: Math.abs(scaleY(0) - yPos),
5793
+ fill: data[seriesIndex].color || colors[seriesIndex % colors.length],
5794
+ className: `cursor-pointer transition-opacity ${barClass}`,
5684
5795
  opacity: isHovered ? 0.8 : 1,
5685
- onMouseEnter: () => showTooltip && setHoveredBar({ seriesIndex, barIndex, x: xPos + barW / 2, y: yPos }),
5686
- onMouseLeave: () => setHoveredBar(null)
5796
+ onMouseEnter: () => {
5797
+ if (showTooltip) {
5798
+ setHoveredBar({ seriesIndex, barIndex, x: xPos + barW / 2, y: yPos });
5799
+ setTooltipPosition(getTooltipPosition(padding.left + xPos + barW / 2, padding.top + yPos));
5800
+ }
5801
+ },
5802
+ onMouseLeave: () => {
5803
+ setHoveredBar(null);
5804
+ setTooltipPosition(null);
5805
+ }
5687
5806
  },
5688
5807
  `bar-${seriesIndex}-${barIndex}`
5689
5808
  )
@@ -5708,8 +5827,8 @@ var BarChart = ({
5708
5827
  y: yPos,
5709
5828
  width: actualBarWidth,
5710
5829
  height: barHeight,
5711
- fill: data[seriesIndex].color || defaultColors2[seriesIndex % defaultColors2.length],
5712
- className: "cursor-pointer transition-opacity",
5830
+ fill: data[seriesIndex].color || colors[seriesIndex % colors.length],
5831
+ className: `cursor-pointer transition-opacity ${barClass}`,
5713
5832
  opacity: isHovered ? 0.8 : 1,
5714
5833
  onMouseEnter: () => showTooltip && setHoveredBar({ seriesIndex, barIndex, x: xPos + actualBarWidth / 2, y: yPos }),
5715
5834
  onMouseLeave: () => setHoveredBar(null)
@@ -5723,10 +5842,11 @@ var BarChart = ({
5723
5842
  "text",
5724
5843
  {
5725
5844
  x: xPos + actualBarWidth / 2,
5726
- y: yPos - 5,
5845
+ y: yPos - 10,
5727
5846
  textAnchor: "middle",
5728
- fontSize: "14",
5729
- fontWeight: "500",
5847
+ dominantBaseline: "middle",
5848
+ fontSize: "11",
5849
+ fontWeight: "600",
5730
5850
  className: "fill-gray-700 dark:fill-gray-300",
5731
5851
  children: point.y
5732
5852
  },
@@ -5745,30 +5865,77 @@ var BarChart = ({
5745
5865
  "text",
5746
5866
  {
5747
5867
  x: xPos,
5748
- y: chartHeight + 20,
5868
+ y: chartHeight + 35,
5749
5869
  textAnchor: "middle",
5750
- fontSize: "14",
5751
- className: "fill-gray-600 dark:fill-gray-400",
5870
+ dominantBaseline: "hanging",
5871
+ fontSize: gridLabelFontSize,
5872
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5752
5873
  children: point.x
5753
5874
  },
5754
5875
  `x-label-${i}`
5755
5876
  );
5756
5877
  });
5878
+ const getTooltipPosition = import_react27.default.useCallback((x, y) => {
5879
+ if (!containerRef.current) return { x, y };
5880
+ const rect = containerRef.current.getBoundingClientRect();
5881
+ const tooltipWidth = 140;
5882
+ const tooltipHeight = 80;
5883
+ let tooltipX = x + 10;
5884
+ let tooltipY = y - 30;
5885
+ if (tooltipX + tooltipWidth > rect.width) {
5886
+ tooltipX = x - tooltipWidth - 10;
5887
+ }
5888
+ if (tooltipY + tooltipHeight > rect.height) {
5889
+ tooltipY = y + 30;
5890
+ }
5891
+ return { x: tooltipX, y: tooltipY };
5892
+ }, []);
5893
+ const containerStyle = {
5894
+ "--font-size-base": `${baseFontSize}px`,
5895
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
5896
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
5897
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`
5898
+ };
5757
5899
  return /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
5758
5900
  "div",
5759
5901
  {
5760
- className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
5761
- style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
5902
+ ref: containerRef,
5903
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
5904
+ style: {
5905
+ ...containerStyle
5906
+ },
5762
5907
  children: [
5908
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("style", { children: `
5909
+ /* Mobile: Large fonts, hidden axis titles, thicker bars (default) */
5910
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
5911
+ .${axisLabelClass} { display: none; }
5912
+
5913
+ /* Tablet: Medium fonts, show axis titles */
5914
+ @media (min-width: 640px) {
5915
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
5916
+ .${axisLabelClass} {
5917
+ font-size: ${axisLabelFontSize * 0.7}px !important;
5918
+ display: block;
5919
+ }
5920
+ }
5921
+
5922
+ /* Desktop: Small fonts, show axis titles */
5923
+ @media (min-width: 1024px) {
5924
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
5925
+ .${axisLabelClass} {
5926
+ font-size: ${axisLabelFontSize * 0.4}px !important;
5927
+ display: block;
5928
+ }
5929
+ }
5930
+ ` }),
5763
5931
  /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5764
5932
  "svg",
5765
5933
  {
5766
5934
  width: "100%",
5767
- height: "100%",
5768
- viewBox: `0 0 ${width} ${height}`,
5935
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
5769
5936
  preserveAspectRatio: "xMidYMid meet",
5770
- className: "bg-white dark:bg-gray-800 block",
5771
- style: { overflow: "visible" },
5937
+ className: "bg-white dark:bg-gray-800 block w-full",
5938
+ style: { height: "auto", overflow: "visible" },
5772
5939
  children: /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5773
5940
  gridLines,
5774
5941
  renderBars(),
@@ -5777,11 +5944,12 @@ var BarChart = ({
5777
5944
  "text",
5778
5945
  {
5779
5946
  x: chartWidth / 2,
5780
- y: chartHeight + 50,
5947
+ y: chartHeight + 80,
5781
5948
  textAnchor: "middle",
5782
- fontSize: "16",
5783
- fontWeight: "500",
5784
- className: "fill-gray-700 dark:fill-gray-300",
5949
+ dominantBaseline: "hanging",
5950
+ fontSize: axisLabelFontSize,
5951
+ fontWeight: "600",
5952
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5785
5953
  children: xAxisLabel
5786
5954
  }
5787
5955
  ),
@@ -5789,41 +5957,43 @@ var BarChart = ({
5789
5957
  "text",
5790
5958
  {
5791
5959
  x: -chartHeight / 2,
5792
- y: -45,
5960
+ y: -100,
5793
5961
  textAnchor: "middle",
5794
- fontSize: "16",
5795
- fontWeight: "500",
5796
- transform: `rotate(-90, 0, 0)`,
5797
- className: "fill-gray-700 dark:fill-gray-300",
5962
+ dominantBaseline: "middle",
5963
+ fontSize: axisLabelFontSize,
5964
+ fontWeight: "600",
5965
+ transform: "rotate(-90)",
5966
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5798
5967
  children: yAxisLabel
5799
5968
  }
5800
5969
  )
5801
5970
  ] })
5802
5971
  }
5803
5972
  ),
5804
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "flex items-center gap-2", children: [
5973
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "flex items-center gap-2 text-sm", children: [
5805
5974
  /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5806
5975
  "div",
5807
5976
  {
5808
- className: "w-4 h-4 rounded-sm",
5977
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
5809
5978
  style: {
5810
- backgroundColor: series.color || defaultColors2[index % defaultColors2.length]
5979
+ backgroundColor: series.color || colors[index % colors.length]
5811
5980
  }
5812
5981
  }
5813
5982
  ),
5814
- /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5983
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("span", { className: "text-gray-700 dark:text-gray-300", children: series.name })
5815
5984
  ] }, `legend-${index}`)) }),
5816
- showTooltip && hoveredBar && /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
5985
+ showTooltip && hoveredBar && tooltipPosition && /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
5817
5986
  "div",
5818
5987
  {
5819
- className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50",
5988
+ className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg pointer-events-none z-50 text-sm whitespace-nowrap",
5820
5989
  style: {
5821
- left: `${padding.left + hoveredBar.x + 10}px`,
5822
- top: `${padding.top + hoveredBar.y - 30}px`
5990
+ left: `${tooltipPosition.x}px`,
5991
+ top: `${tooltipPosition.y}px`,
5992
+ transform: "translateZ(0)"
5823
5993
  },
5824
5994
  children: [
5825
5995
  /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "font-semibold", children: data[hoveredBar.seriesIndex].name }),
5826
- /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { children: [
5996
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "text-xs opacity-90", children: [
5827
5997
  data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].x,
5828
5998
  ": ",
5829
5999
  data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].y
@@ -5871,14 +6041,32 @@ var AreaChart = ({
5871
6041
  strokeWidth = 2,
5872
6042
  className = "",
5873
6043
  xAxisLabel,
5874
- yAxisLabel
6044
+ yAxisLabel,
6045
+ baseFontSize = 14
5875
6046
  }) => {
5876
- const height = providedHeight ?? 400;
5877
- const width = providedWidth ?? 800;
6047
+ const viewBoxWidth = 1e3;
6048
+ const viewBoxHeight = 600;
6049
+ const containerRef = import_react28.default.useRef(null);
6050
+ const svgRef = import_react28.default.useRef(null);
6051
+ const [tooltipPosition, setTooltipPosition] = import_react28.default.useState(null);
5878
6052
  const [hoveredPoint, setHoveredPoint] = import_react28.default.useState(null);
5879
- const padding = { top: 20, right: 20, bottom: showXAxis ? 60 : 20, left: showYAxis ? 60 : 20 };
5880
- const chartWidth = width - padding.left - padding.right;
5881
- const chartHeight = height - padding.top - padding.bottom;
6053
+ const chartId = import_react28.default.useId();
6054
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
6055
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
6056
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
6057
+ const lineClass = `chart-line-${chartId.replace(/:/g, "-")}`;
6058
+ const pointClass = `chart-point-${chartId.replace(/:/g, "-")}`;
6059
+ const padding = {
6060
+ top: 50,
6061
+ right: 50,
6062
+ bottom: showXAxis ? 120 : 50,
6063
+ left: showYAxis ? 130 : 50
6064
+ };
6065
+ const chartWidth = viewBoxWidth - padding.left - padding.right;
6066
+ const chartHeight = viewBoxHeight - padding.top - padding.bottom;
6067
+ const gridLabelFontSize = viewBoxWidth * 0.045;
6068
+ const axisLabelFontSize = viewBoxWidth * 0.05;
6069
+ const titleFontSize = viewBoxWidth * 0.055;
5882
6070
  const allPoints = data.flatMap((series) => series.data);
5883
6071
  const allYValues = stacked ? data[0]?.data.map(
5884
6072
  (_, i) => data.reduce((sum, series) => sum + (series.data[i]?.y || 0), 0)
@@ -5892,7 +6080,7 @@ var AreaChart = ({
5892
6080
  const minY = Math.min(0, ...allYValues);
5893
6081
  const maxY = Math.max(...allYValues);
5894
6082
  const yRange = maxY - minY;
5895
- const yMin = minY - yRange * 0.1;
6083
+ const yMin = Math.max(0, minY - yRange * 0.1);
5896
6084
  const yMax = maxY + yRange * 0.1;
5897
6085
  const scaleX = (x, index) => {
5898
6086
  const numX = isStringX ? index : x;
@@ -5973,20 +6161,21 @@ var AreaChart = ({
5973
6161
  x2: chartWidth,
5974
6162
  y2: y,
5975
6163
  stroke: "currentColor",
5976
- strokeWidth: "1",
6164
+ strokeWidth: "0.5",
5977
6165
  className: "text-gray-200 dark:text-gray-700",
5978
- strokeDasharray: "2,2"
6166
+ strokeDasharray: "4,4"
5979
6167
  }
5980
6168
  ),
5981
6169
  showYAxis && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5982
6170
  "text",
5983
6171
  {
5984
- x: -10,
5985
- y: y + 4,
6172
+ x: -25,
6173
+ y,
5986
6174
  textAnchor: "end",
5987
- fontSize: "12",
5988
- className: "fill-gray-600 dark:fill-gray-400",
5989
- children: yValue.toFixed(0)
6175
+ dominantBaseline: "middle",
6176
+ fontSize: gridLabelFontSize,
6177
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
6178
+ children: yValue.toFixed(1)
5990
6179
  }
5991
6180
  )
5992
6181
  ] }, `grid-h-${i}`)
@@ -6006,19 +6195,20 @@ var AreaChart = ({
6006
6195
  x2: x,
6007
6196
  y2: chartHeight,
6008
6197
  stroke: "currentColor",
6009
- strokeWidth: "1",
6198
+ strokeWidth: "0.5",
6010
6199
  className: "text-gray-200 dark:text-gray-700",
6011
- strokeDasharray: "2,2"
6200
+ strokeDasharray: "4,4"
6012
6201
  }
6013
6202
  ),
6014
6203
  showXAxis && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6015
6204
  "text",
6016
6205
  {
6017
6206
  x,
6018
- y: chartHeight + 20,
6207
+ y: chartHeight + 35,
6019
6208
  textAnchor: "middle",
6020
- fontSize: "12",
6021
- className: "fill-gray-600 dark:fill-gray-400",
6209
+ dominantBaseline: "hanging",
6210
+ fontSize: gridLabelFontSize,
6211
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
6022
6212
  children: xValue
6023
6213
  }
6024
6214
  )
@@ -6030,20 +6220,72 @@ var AreaChart = ({
6030
6220
  if (stacked) {
6031
6221
  cumulativeValues = Array(data[0]?.data.length || 0).fill(0);
6032
6222
  }
6223
+ const getTooltipPosition = import_react28.default.useCallback((x, y) => {
6224
+ if (!containerRef.current) return { x, y };
6225
+ const rect = containerRef.current.getBoundingClientRect();
6226
+ const tooltipWidth = 120;
6227
+ const tooltipHeight = 80;
6228
+ let tooltipX = x + 10;
6229
+ let tooltipY = y - 30;
6230
+ if (tooltipX + tooltipWidth > rect.width) {
6231
+ tooltipX = x - tooltipWidth - 10;
6232
+ }
6233
+ if (tooltipY + tooltipHeight > rect.height) {
6234
+ tooltipY = y + 30;
6235
+ }
6236
+ return { x: tooltipX, y: tooltipY };
6237
+ }, []);
6238
+ const containerStyle = {
6239
+ "--font-size-base": `${baseFontSize}px`,
6240
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
6241
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
6242
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`
6243
+ };
6033
6244
  return /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)(
6034
6245
  "div",
6035
6246
  {
6036
- className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
6037
- style: responsive ? { width: "100%", aspectRatio: `${width} / ${height}` } : void 0,
6247
+ ref: containerRef,
6248
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
6249
+ style: containerStyle,
6038
6250
  children: [
6251
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("style", { children: `
6252
+ /* Mobile: Large fonts, hidden axis titles, thicker lines (default) */
6253
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
6254
+ .${axisLabelClass} { display: none; }
6255
+ .${lineClass} { stroke-width: ${strokeWidth * 2.5} !important; }
6256
+ .${pointClass} { r: 6 !important; stroke-width: 3 !important; }
6257
+
6258
+ /* Tablet: Medium fonts, show axis titles, medium lines */
6259
+ @media (min-width: 640px) {
6260
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
6261
+ .${axisLabelClass} {
6262
+ font-size: ${axisLabelFontSize * 0.7}px !important;
6263
+ display: block;
6264
+ }
6265
+ .${lineClass} { stroke-width: ${strokeWidth * 1.5} !important; }
6266
+ .${pointClass} { r: 4 !important; stroke-width: 2 !important; }
6267
+ }
6268
+
6269
+ /* Desktop: Small fonts, show axis titles, normal lines */
6270
+ @media (min-width: 1024px) {
6271
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
6272
+ .${axisLabelClass} {
6273
+ font-size: ${axisLabelFontSize * 0.4}px !important;
6274
+ display: block;
6275
+ }
6276
+ .${lineClass} { stroke-width: ${strokeWidth} !important; }
6277
+ .${pointClass} { r: 3 !important; stroke-width: 1.5 !important; }
6278
+ }
6279
+ ` }),
6039
6280
  /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6040
6281
  "svg",
6041
6282
  {
6283
+ ref: svgRef,
6042
6284
  width: "100%",
6043
- height: "100%",
6044
- viewBox: `0 0 ${width} ${height}`,
6285
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
6045
6286
  preserveAspectRatio: "xMidYMid meet",
6046
- className: "bg-white dark:bg-gray-800 block",
6287
+ className: "bg-white dark:bg-gray-800 block w-full",
6288
+ style: { height: "auto", overflow: "visible" },
6047
6289
  children: /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
6048
6290
  gridLines,
6049
6291
  data.map((series, seriesIndex) => {
@@ -6072,7 +6314,8 @@ var AreaChart = ({
6072
6314
  stroke: series.color || defaultColors3[seriesIndex % defaultColors3.length],
6073
6315
  strokeWidth,
6074
6316
  strokeLinecap: "round",
6075
- strokeLinejoin: "round"
6317
+ strokeLinejoin: "round",
6318
+ className: lineClass
6076
6319
  }
6077
6320
  )
6078
6321
  ] }, `area-${seriesIndex}`);
@@ -6094,9 +6337,28 @@ var AreaChart = ({
6094
6337
  fill: series.color || defaultColors3[seriesIndex % defaultColors3.length],
6095
6338
  stroke: "white",
6096
6339
  strokeWidth: "2",
6097
- className: "cursor-pointer transition-all",
6098
- onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
6099
- onMouseLeave: () => setHoveredPoint(null)
6340
+ className: `cursor-pointer transition-all ${pointClass}`,
6341
+ onMouseEnter: (e) => {
6342
+ if (showTooltip && containerRef.current) {
6343
+ setHoveredPoint({ seriesIndex, pointIndex, x, y });
6344
+ const containerRect = containerRef.current.getBoundingClientRect();
6345
+ const mouseX = e.clientX - containerRect.left;
6346
+ const mouseY = e.clientY - containerRect.top;
6347
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
6348
+ }
6349
+ },
6350
+ onMouseMove: (e) => {
6351
+ if (showTooltip && hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex && containerRef.current) {
6352
+ const containerRect = containerRef.current.getBoundingClientRect();
6353
+ const mouseX = e.clientX - containerRect.left;
6354
+ const mouseY = e.clientY - containerRect.top;
6355
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
6356
+ }
6357
+ },
6358
+ onMouseLeave: () => {
6359
+ setHoveredPoint(null);
6360
+ setTooltipPosition(null);
6361
+ }
6100
6362
  },
6101
6363
  `point-${seriesIndex}-${pointIndex}`
6102
6364
  );
@@ -6106,11 +6368,12 @@ var AreaChart = ({
6106
6368
  "text",
6107
6369
  {
6108
6370
  x: chartWidth / 2,
6109
- y: chartHeight + 50,
6371
+ y: chartHeight + 80,
6110
6372
  textAnchor: "middle",
6111
- fontSize: "14",
6112
- fontWeight: "500",
6113
- className: "fill-gray-700 dark:fill-gray-300",
6373
+ dominantBaseline: "hanging",
6374
+ fontSize: axisLabelFontSize,
6375
+ fontWeight: "600",
6376
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
6114
6377
  children: xAxisLabel
6115
6378
  }
6116
6379
  ),
@@ -6118,45 +6381,47 @@ var AreaChart = ({
6118
6381
  "text",
6119
6382
  {
6120
6383
  x: -chartHeight / 2,
6121
- y: -45,
6384
+ y: -100,
6122
6385
  textAnchor: "middle",
6123
- fontSize: "14",
6124
- fontWeight: "500",
6125
- transform: "rotate(-90, 0, 0)",
6126
- className: "fill-gray-700 dark:fill-gray-300",
6386
+ dominantBaseline: "middle",
6387
+ fontSize: axisLabelFontSize,
6388
+ fontWeight: "600",
6389
+ transform: "rotate(-90)",
6390
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
6127
6391
  children: yAxisLabel
6128
6392
  }
6129
6393
  )
6130
6394
  ] })
6131
6395
  }
6132
6396
  ),
6133
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { className: "flex items-center gap-2", children: [
6397
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { className: "flex items-center gap-2 text-sm", children: [
6134
6398
  /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6135
6399
  "div",
6136
6400
  {
6137
- className: "w-4 h-4 rounded-sm",
6401
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
6138
6402
  style: {
6139
6403
  backgroundColor: series.color || defaultColors3[index % defaultColors3.length]
6140
6404
  }
6141
6405
  }
6142
6406
  ),
6143
- /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
6407
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("span", { className: "text-gray-700 dark:text-gray-300", children: series.name })
6144
6408
  ] }, `legend-${index}`)) }),
6145
- showTooltip && hoveredPoint && /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)(
6409
+ showTooltip && hoveredPoint && tooltipPosition && /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)(
6146
6410
  "div",
6147
6411
  {
6148
- className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50",
6412
+ className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg pointer-events-none z-50 text-sm whitespace-nowrap",
6149
6413
  style: {
6150
- left: `${padding.left + hoveredPoint.x + 10}px`,
6151
- top: `${padding.top + hoveredPoint.y - 30}px`
6414
+ left: `${tooltipPosition.x}px`,
6415
+ top: `${tooltipPosition.y}px`,
6416
+ transform: "translateZ(0)"
6152
6417
  },
6153
6418
  children: [
6154
6419
  /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
6155
- /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { children: [
6420
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { className: "text-xs opacity-90", children: [
6156
6421
  "x: ",
6157
6422
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
6158
6423
  ] }),
6159
- /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { children: [
6424
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { className: "text-xs opacity-90", children: [
6160
6425
  "y: ",
6161
6426
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
6162
6427
  ] })
@@ -6201,16 +6466,27 @@ var PieChart = ({
6201
6466
  showPercentages = false,
6202
6467
  donut = false,
6203
6468
  donutWidth = 60,
6204
- className = ""
6469
+ className = "",
6470
+ baseFontSize = 14
6205
6471
  }) => {
6206
- const height = providedHeight ?? 400;
6207
- const width = providedWidth ?? 400;
6472
+ const viewBoxWidth = 600;
6473
+ const viewBoxHeight = 600;
6474
+ const containerRef = import_react29.default.useRef(null);
6475
+ const [tooltipPosition, setTooltipPosition] = import_react29.default.useState(null);
6208
6476
  const [hoveredSlice, setHoveredSlice] = import_react29.default.useState(null);
6477
+ const chartId = import_react29.default.useId();
6478
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
6479
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
6480
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
6481
+ const sliceClass = `chart-slice-${chartId.replace(/:/g, "-")}`;
6209
6482
  const total = data.reduce((sum, item) => sum + item.value, 0);
6210
- const centerX = width / 2;
6211
- const centerY = height / 2;
6212
- const radius = Math.min(width, height) / 2 - 40;
6483
+ const centerX = viewBoxWidth / 2;
6484
+ const centerY = viewBoxHeight / 2;
6485
+ const radius = Math.min(viewBoxWidth, viewBoxHeight) / 2 - 40;
6213
6486
  const innerRadius = donut ? radius - donutWidth : 0;
6487
+ const gridLabelFontSize = viewBoxWidth * 0.045;
6488
+ const axisLabelFontSize = viewBoxWidth * 0.05;
6489
+ const titleFontSize = viewBoxWidth * 0.055;
6214
6490
  let currentAngle = -90;
6215
6491
  const slices = data.map((item, index) => {
6216
6492
  const percentage = item.value / total * 100;
@@ -6262,20 +6538,64 @@ var PieChart = ({
6262
6538
  index
6263
6539
  };
6264
6540
  });
6541
+ const getTooltipPosition = import_react29.default.useCallback((x, y) => {
6542
+ if (!containerRef.current) return { x, y };
6543
+ const rect = containerRef.current.getBoundingClientRect();
6544
+ const tooltipWidth = 120;
6545
+ const tooltipHeight = 80;
6546
+ let tooltipX = x + 10;
6547
+ let tooltipY = y - 30;
6548
+ if (tooltipX + tooltipWidth > rect.width) {
6549
+ tooltipX = x - tooltipWidth - 10;
6550
+ }
6551
+ if (tooltipY + tooltipHeight > rect.height) {
6552
+ tooltipY = y + 30;
6553
+ }
6554
+ return { x: tooltipX, y: tooltipY };
6555
+ }, []);
6556
+ const containerStyle = {
6557
+ "--font-size-base": `${baseFontSize}px`,
6558
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
6559
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
6560
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`,
6561
+ "--font-size-xl": `calc(var(--font-size-base) * 1.5)`,
6562
+ "--font-size-2xl": `calc(var(--font-size-base) * 2)`
6563
+ };
6564
+ if (responsive) {
6565
+ containerStyle["--font-size-base"] = `clamp(${baseFontSize * 0.8}px, 4vw, ${baseFontSize}px)`;
6566
+ }
6265
6567
  return /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6266
6568
  "div",
6267
6569
  {
6268
- className: `relative ${responsive ? "w-full flex justify-center" : "inline-block"} ${className}`,
6269
- style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
6570
+ ref: containerRef,
6571
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
6572
+ style: containerStyle,
6270
6573
  children: [
6574
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("style", { children: `
6575
+ /* Mobile: Large fonts (default) */
6576
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
6577
+ .${axisLabelClass} { font-size: ${titleFontSize}px !important; }
6578
+
6579
+ /* Tablet: Medium fonts */
6580
+ @media (min-width: 640px) {
6581
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
6582
+ .${axisLabelClass} { font-size: ${titleFontSize * 0.7}px !important; }
6583
+ }
6584
+
6585
+ /* Desktop: Small fonts */
6586
+ @media (min-width: 1024px) {
6587
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
6588
+ .${axisLabelClass} { font-size: ${titleFontSize * 0.4}px !important; }
6589
+ }
6590
+ ` }),
6271
6591
  /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6272
6592
  "svg",
6273
6593
  {
6274
6594
  width: "100%",
6275
- height: "100%",
6276
- viewBox: `0 0 ${width} ${height}`,
6595
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
6277
6596
  preserveAspectRatio: "xMidYMid meet",
6278
- className: "bg-white dark:bg-gray-800 block",
6597
+ className: "bg-white dark:bg-gray-800 block w-full",
6598
+ style: { height: "auto", overflow: "visible" },
6279
6599
  children: [
6280
6600
  slices.map((slice) => {
6281
6601
  const isHovered = hoveredSlice === slice.index;
@@ -6289,8 +6609,19 @@ var PieChart = ({
6289
6609
  strokeWidth: "2",
6290
6610
  className: "cursor-pointer transition-opacity",
6291
6611
  opacity: isHovered ? 0.8 : 1,
6292
- onMouseEnter: () => setHoveredSlice(slice.index),
6293
- onMouseLeave: () => setHoveredSlice(null)
6612
+ onMouseEnter: (e) => {
6613
+ setHoveredSlice(slice.index);
6614
+ if (containerRef.current) {
6615
+ const rect = containerRef.current.getBoundingClientRect();
6616
+ const svgX = e.clientX - rect.left;
6617
+ const svgY = e.clientY - rect.top;
6618
+ setTooltipPosition(getTooltipPosition(svgX, svgY));
6619
+ }
6620
+ },
6621
+ onMouseLeave: () => {
6622
+ setHoveredSlice(null);
6623
+ setTooltipPosition(null);
6624
+ }
6294
6625
  }
6295
6626
  ),
6296
6627
  showLabels && slice.percentage > 5 && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
@@ -6300,9 +6631,9 @@ var PieChart = ({
6300
6631
  y: slice.labelY,
6301
6632
  textAnchor: "middle",
6302
6633
  dominantBaseline: "middle",
6303
- fontSize: "14",
6634
+ fontSize: gridLabelFontSize,
6304
6635
  fontWeight: "600",
6305
- className: "fill-gray-700 dark:fill-gray-200 pointer-events-none",
6636
+ className: `fill-gray-700 dark:fill-gray-200 pointer-events-none ${gridLabelClass}`,
6306
6637
  children: [
6307
6638
  showPercentages && `${slice.percentage.toFixed(1)}%`,
6308
6639
  showPercentages && showValues && " ",
@@ -6320,9 +6651,10 @@ var PieChart = ({
6320
6651
  x: centerX,
6321
6652
  y: centerY - 10,
6322
6653
  textAnchor: "middle",
6323
- fontSize: "32",
6654
+ dominantBaseline: "middle",
6655
+ fontSize: titleFontSize,
6324
6656
  fontWeight: "700",
6325
- className: "fill-gray-900 dark:fill-gray-100",
6657
+ className: `fill-gray-900 dark:fill-gray-100 ${axisLabelClass}`,
6326
6658
  children: total
6327
6659
  }
6328
6660
  ),
@@ -6332,8 +6664,9 @@ var PieChart = ({
6332
6664
  x: centerX,
6333
6665
  y: centerY + 15,
6334
6666
  textAnchor: "middle",
6335
- fontSize: "16",
6336
- className: "fill-gray-600 dark:fill-gray-400",
6667
+ dominantBaseline: "middle",
6668
+ fontSize: axisLabelFontSize,
6669
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
6337
6670
  children: "Total"
6338
6671
  }
6339
6672
  )
@@ -6341,23 +6674,23 @@ var PieChart = ({
6341
6674
  ]
6342
6675
  }
6343
6676
  ),
6344
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6677
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6345
6678
  "div",
6346
6679
  {
6347
- className: "flex items-center gap-2 cursor-pointer",
6680
+ className: "flex items-center gap-2 text-sm cursor-pointer",
6348
6681
  onMouseEnter: () => setHoveredSlice(index),
6349
6682
  onMouseLeave: () => setHoveredSlice(null),
6350
6683
  children: [
6351
6684
  /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6352
6685
  "div",
6353
6686
  {
6354
- className: "w-4 h-4 rounded-sm",
6687
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
6355
6688
  style: {
6356
6689
  backgroundColor: item.color || defaultColors4[index % defaultColors4.length]
6357
6690
  }
6358
6691
  }
6359
6692
  ),
6360
- /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: [
6693
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("span", { className: "text-gray-700 dark:text-gray-300", children: [
6361
6694
  item.label,
6362
6695
  ": ",
6363
6696
  item.value,
@@ -6367,18 +6700,29 @@ var PieChart = ({
6367
6700
  },
6368
6701
  `legend-${index}`
6369
6702
  )) }),
6370
- hoveredSlice !== null && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { className: "absolute top-2 right-2 bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50", children: [
6371
- /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "font-semibold", children: data[hoveredSlice].label }),
6372
- /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { children: [
6373
- "Value: ",
6374
- data[hoveredSlice].value
6375
- ] }),
6376
- /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { children: [
6377
- "Percentage: ",
6378
- (data[hoveredSlice].value / total * 100).toFixed(1),
6379
- "%"
6380
- ] })
6381
- ] })
6703
+ hoveredSlice !== null && tooltipPosition && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6704
+ "div",
6705
+ {
6706
+ className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg pointer-events-none z-50 text-sm whitespace-nowrap",
6707
+ style: {
6708
+ left: `${tooltipPosition.x}px`,
6709
+ top: `${tooltipPosition.y}px`,
6710
+ transform: "translateZ(0)"
6711
+ },
6712
+ children: [
6713
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "font-semibold", children: data[hoveredSlice].label }),
6714
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { className: "text-xs opacity-90", children: [
6715
+ "Value: ",
6716
+ data[hoveredSlice].value
6717
+ ] }),
6718
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { className: "text-xs opacity-90", children: [
6719
+ "Percentage: ",
6720
+ (data[hoveredSlice].value / total * 100).toFixed(1),
6721
+ "%"
6722
+ ] })
6723
+ ]
6724
+ }
6725
+ )
6382
6726
  ]
6383
6727
  }
6384
6728
  );