@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.mjs CHANGED
@@ -5149,14 +5149,32 @@ var LineChart = ({
5149
5149
  strokeWidth = 2,
5150
5150
  className = "",
5151
5151
  xAxisLabel,
5152
- yAxisLabel
5152
+ yAxisLabel,
5153
+ baseFontSize = 14
5153
5154
  }) => {
5154
- const height = providedHeight ?? 400;
5155
- const width = providedWidth ?? (responsive ? 600 : 600);
5155
+ const viewBoxWidth = 1e3;
5156
+ const viewBoxHeight = 600;
5157
+ const containerRef = React26.useRef(null);
5158
+ const svgRef = React26.useRef(null);
5159
+ const [tooltipPosition, setTooltipPosition] = React26.useState(null);
5156
5160
  const [hoveredPoint, setHoveredPoint] = React26.useState(null);
5157
- const padding = { top: 20, right: 20, bottom: showXAxis ? 60 : 20, left: showYAxis ? 60 : 20 };
5158
- const chartWidth = width - padding.left - padding.right;
5159
- const chartHeight = height - padding.top - padding.bottom;
5161
+ const chartId = React26.useId();
5162
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
5163
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
5164
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
5165
+ const lineClass = `chart-line-${chartId.replace(/:/g, "-")}`;
5166
+ const pointClass = `chart-point-${chartId.replace(/:/g, "-")}`;
5167
+ const padding = {
5168
+ top: 50,
5169
+ right: 50,
5170
+ bottom: showXAxis ? 120 : 50,
5171
+ left: showYAxis ? 130 : 50
5172
+ };
5173
+ const chartWidth = viewBoxWidth - padding.left - padding.right;
5174
+ const chartHeight = viewBoxHeight - padding.top - padding.bottom;
5175
+ const gridLabelFontSize = viewBoxWidth * 0.045;
5176
+ const axisLabelFontSize = viewBoxWidth * 0.05;
5177
+ const titleFontSize = viewBoxWidth * 0.055;
5160
5178
  const allPoints = data.flatMap((series) => series.data);
5161
5179
  const allYValues = allPoints.map((p) => p.y);
5162
5180
  const firstXValue = data[0]?.data[0]?.x;
@@ -5169,7 +5187,7 @@ var LineChart = ({
5169
5187
  const minY = Math.min(0, ...allYValues);
5170
5188
  const maxY = Math.max(...allYValues);
5171
5189
  const yRange = maxY - minY;
5172
- const yMin = minY - yRange * 0.1;
5190
+ const yMin = Math.max(0, minY - yRange * 0.1);
5173
5191
  const yMax = maxY + yRange * 0.1;
5174
5192
  const scaleX = (x, index) => {
5175
5193
  const numX = isStringX ? index : x;
@@ -5216,29 +5234,32 @@ var LineChart = ({
5216
5234
  x2: chartWidth,
5217
5235
  y2: y,
5218
5236
  stroke: "currentColor",
5219
- strokeWidth: "1",
5237
+ strokeWidth: "0.5",
5220
5238
  className: "text-gray-200 dark:text-gray-700",
5221
- strokeDasharray: "2,2"
5239
+ strokeDasharray: "4,4"
5222
5240
  }
5223
5241
  ),
5224
5242
  showYAxis && /* @__PURE__ */ jsx108(
5225
5243
  "text",
5226
5244
  {
5227
- x: -10,
5228
- y: y + 4,
5245
+ x: -25,
5246
+ y,
5229
5247
  textAnchor: "end",
5230
- fontSize: "16",
5231
- className: "fill-gray-600 dark:fill-gray-400",
5248
+ dominantBaseline: "middle",
5249
+ fontSize: gridLabelFontSize,
5250
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5232
5251
  children: yValue.toFixed(1)
5233
5252
  }
5234
5253
  )
5235
5254
  ] }, `grid-h-${i}`)
5236
5255
  );
5237
5256
  }
5238
- const numXGridLines = Math.min(allPoints.length, 6);
5257
+ const numXGridLines = Math.max(2, Math.min(allPoints.length, 6));
5258
+ const xGridStep = numXGridLines > 1 ? 1 / (numXGridLines - 1) : 0;
5239
5259
  for (let i = 0; i < numXGridLines; i++) {
5240
- const x = chartWidth / (numXGridLines - 1) * i;
5241
- const xValue = data[0]?.data[Math.floor((data[0].data.length - 1) * (i / (numXGridLines - 1)))]?.x || "";
5260
+ const x = chartWidth * (i * xGridStep);
5261
+ const dataIndex = Math.floor((data[0]?.data.length - 1) * (i * xGridStep));
5262
+ const xValue = data[0]?.data[Math.max(0, Math.min(dataIndex, data[0].data.length - 1))]?.x || "";
5242
5263
  gridLines.push(
5243
5264
  /* @__PURE__ */ jsxs35("g", { children: [
5244
5265
  /* @__PURE__ */ jsx108(
@@ -5249,19 +5270,20 @@ var LineChart = ({
5249
5270
  x2: x,
5250
5271
  y2: chartHeight,
5251
5272
  stroke: "currentColor",
5252
- strokeWidth: "1",
5273
+ strokeWidth: "0.5",
5253
5274
  className: "text-gray-200 dark:text-gray-700",
5254
- strokeDasharray: "2,2"
5275
+ strokeDasharray: "4,4"
5255
5276
  }
5256
5277
  ),
5257
5278
  showXAxis && /* @__PURE__ */ jsx108(
5258
5279
  "text",
5259
5280
  {
5260
5281
  x,
5261
- y: chartHeight + 20,
5282
+ y: chartHeight + 35,
5262
5283
  textAnchor: "middle",
5263
- fontSize: "14",
5264
- className: "fill-gray-600 dark:fill-gray-400",
5284
+ dominantBaseline: "hanging",
5285
+ fontSize: gridLabelFontSize,
5286
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5265
5287
  children: xValue
5266
5288
  }
5267
5289
  )
@@ -5269,21 +5291,74 @@ var LineChart = ({
5269
5291
  );
5270
5292
  }
5271
5293
  }
5294
+ const getTooltipPosition = React26.useCallback((x, y) => {
5295
+ if (!containerRef.current) return { x, y };
5296
+ const rect = containerRef.current.getBoundingClientRect();
5297
+ const tooltipWidth = 120;
5298
+ const tooltipHeight = 80;
5299
+ let tooltipX = x + 10;
5300
+ let tooltipY = y - 30;
5301
+ if (tooltipX + tooltipWidth > rect.width) {
5302
+ tooltipX = x - tooltipWidth - 10;
5303
+ }
5304
+ if (tooltipY + tooltipHeight > rect.height) {
5305
+ tooltipY = y + 30;
5306
+ }
5307
+ return { x: tooltipX, y: tooltipY };
5308
+ }, []);
5309
+ const containerStyle = {
5310
+ "--font-size-base": `${baseFontSize}px`,
5311
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
5312
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
5313
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`
5314
+ };
5272
5315
  return /* @__PURE__ */ jsxs35(
5273
5316
  "div",
5274
5317
  {
5275
- className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
5276
- style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
5318
+ ref: containerRef,
5319
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
5320
+ style: {
5321
+ ...containerStyle
5322
+ },
5277
5323
  children: [
5324
+ /* @__PURE__ */ jsx108("style", { children: `
5325
+ /* Mobile: Large fonts, hidden axis titles, thicker lines (default) */
5326
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
5327
+ .${axisLabelClass} { display: none; }
5328
+ .${lineClass} { stroke-width: ${strokeWidth * 2.5} !important; }
5329
+ .${pointClass} { r: 6 !important; stroke-width: 3 !important; }
5330
+
5331
+ /* Tablet: Medium fonts, show axis titles, medium lines */
5332
+ @media (min-width: 640px) {
5333
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
5334
+ .${axisLabelClass} {
5335
+ font-size: ${axisLabelFontSize * 0.7}px !important;
5336
+ display: block;
5337
+ }
5338
+ .${lineClass} { stroke-width: ${strokeWidth * 1.5} !important; }
5339
+ .${pointClass} { r: 4 !important; stroke-width: 2 !important; }
5340
+ }
5341
+
5342
+ /* Desktop: Small fonts, show axis titles, normal lines */
5343
+ @media (min-width: 1024px) {
5344
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
5345
+ .${axisLabelClass} {
5346
+ font-size: ${axisLabelFontSize * 0.4}px !important;
5347
+ display: block;
5348
+ }
5349
+ .${lineClass} { stroke-width: ${strokeWidth} !important; }
5350
+ .${pointClass} { r: 3 !important; stroke-width: 1.5 !important; }
5351
+ }
5352
+ ` }),
5278
5353
  /* @__PURE__ */ jsx108(
5279
5354
  "svg",
5280
5355
  {
5356
+ ref: svgRef,
5281
5357
  width: "100%",
5282
- height: "100%",
5283
- viewBox: `0 0 ${width} ${height}`,
5358
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
5284
5359
  preserveAspectRatio: "xMidYMid meet",
5285
- className: "bg-white dark:bg-gray-800 block",
5286
- style: { overflow: "visible" },
5360
+ className: "bg-white dark:bg-gray-800 block w-full",
5361
+ style: { height: "auto", overflow: "visible" },
5287
5362
  children: /* @__PURE__ */ jsxs35("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5288
5363
  gridLines,
5289
5364
  data.map((series, seriesIndex) => /* @__PURE__ */ jsx108(
@@ -5294,7 +5369,8 @@ var LineChart = ({
5294
5369
  stroke: series.color || defaultColors[seriesIndex % defaultColors.length],
5295
5370
  strokeWidth,
5296
5371
  strokeLinecap: "round",
5297
- strokeLinejoin: "round"
5372
+ strokeLinejoin: "round",
5373
+ className: lineClass
5298
5374
  },
5299
5375
  `line-${seriesIndex}`
5300
5376
  )),
@@ -5308,13 +5384,32 @@ var LineChart = ({
5308
5384
  {
5309
5385
  cx: x,
5310
5386
  cy: y,
5311
- r: isHovered ? 6 : 4,
5387
+ r: isHovered ? 5 : 3,
5312
5388
  fill: series.color || defaultColors[seriesIndex % defaultColors.length],
5313
5389
  stroke: "white",
5314
- strokeWidth: "2",
5315
- className: "cursor-pointer transition-all",
5316
- onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
5317
- onMouseLeave: () => setHoveredPoint(null)
5390
+ strokeWidth: "1.5",
5391
+ className: `cursor-pointer transition-all ${pointClass}`,
5392
+ onMouseEnter: (e) => {
5393
+ if (showTooltip && containerRef.current) {
5394
+ setHoveredPoint({ seriesIndex, pointIndex, x, y });
5395
+ const containerRect = containerRef.current.getBoundingClientRect();
5396
+ const mouseX = e.clientX - containerRect.left;
5397
+ const mouseY = e.clientY - containerRect.top;
5398
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
5399
+ }
5400
+ },
5401
+ onMouseMove: (e) => {
5402
+ if (showTooltip && hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex && containerRef.current) {
5403
+ const containerRect = containerRef.current.getBoundingClientRect();
5404
+ const mouseX = e.clientX - containerRect.left;
5405
+ const mouseY = e.clientY - containerRect.top;
5406
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
5407
+ }
5408
+ },
5409
+ onMouseLeave: () => {
5410
+ setHoveredPoint(null);
5411
+ setTooltipPosition(null);
5412
+ }
5318
5413
  },
5319
5414
  `point-${seriesIndex}-${pointIndex}`
5320
5415
  );
@@ -5324,11 +5419,12 @@ var LineChart = ({
5324
5419
  "text",
5325
5420
  {
5326
5421
  x: chartWidth / 2,
5327
- y: chartHeight + 50,
5422
+ y: chartHeight + 80,
5328
5423
  textAnchor: "middle",
5329
- fontSize: "16",
5330
- fontWeight: "500",
5331
- className: "fill-gray-700 dark:fill-gray-300",
5424
+ dominantBaseline: "hanging",
5425
+ fontSize: axisLabelFontSize,
5426
+ fontWeight: "600",
5427
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5332
5428
  children: xAxisLabel
5333
5429
  }
5334
5430
  ),
@@ -5336,45 +5432,47 @@ var LineChart = ({
5336
5432
  "text",
5337
5433
  {
5338
5434
  x: -chartHeight / 2,
5339
- y: -45,
5435
+ y: -100,
5340
5436
  textAnchor: "middle",
5341
- fontSize: "16",
5342
- fontWeight: "500",
5343
- transform: `rotate(-90, 0, 0)`,
5344
- className: "fill-gray-700 dark:fill-gray-300",
5437
+ dominantBaseline: "middle",
5438
+ fontSize: axisLabelFontSize,
5439
+ fontWeight: "600",
5440
+ transform: "rotate(-90)",
5441
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5345
5442
  children: yAxisLabel
5346
5443
  }
5347
5444
  )
5348
5445
  ] })
5349
5446
  }
5350
5447
  ),
5351
- showLegend && /* @__PURE__ */ jsx108("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2", children: [
5448
+ showLegend && /* @__PURE__ */ jsx108("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((series, index) => /* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2 text-sm", children: [
5352
5449
  /* @__PURE__ */ jsx108(
5353
5450
  "div",
5354
5451
  {
5355
- className: "w-4 h-4 rounded-sm",
5452
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
5356
5453
  style: {
5357
5454
  backgroundColor: series.color || defaultColors[index % defaultColors.length]
5358
5455
  }
5359
5456
  }
5360
5457
  ),
5361
- /* @__PURE__ */ jsx108("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5458
+ /* @__PURE__ */ jsx108("span", { className: "text-gray-700 dark:text-gray-300", children: series.name })
5362
5459
  ] }, `legend-${index}`)) }),
5363
- showTooltip && hoveredPoint && /* @__PURE__ */ jsxs35(
5460
+ showTooltip && hoveredPoint && tooltipPosition && /* @__PURE__ */ jsxs35(
5364
5461
  "div",
5365
5462
  {
5366
- 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",
5463
+ 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",
5367
5464
  style: {
5368
- left: `${padding.left + hoveredPoint.x + 10}px`,
5369
- top: `${padding.top + hoveredPoint.y - 30}px`
5465
+ left: `${tooltipPosition.x}px`,
5466
+ top: `${tooltipPosition.y}px`,
5467
+ transform: "translateZ(0)"
5370
5468
  },
5371
5469
  children: [
5372
5470
  /* @__PURE__ */ jsx108("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
5373
- /* @__PURE__ */ jsxs35("div", { children: [
5471
+ /* @__PURE__ */ jsxs35("div", { className: "text-xs opacity-90", children: [
5374
5472
  "x: ",
5375
5473
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
5376
5474
  ] }),
5377
- /* @__PURE__ */ jsxs35("div", { children: [
5475
+ /* @__PURE__ */ jsxs35("div", { className: "text-xs opacity-90", children: [
5378
5476
  "y: ",
5379
5477
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
5380
5478
  ] })
@@ -5420,26 +5518,38 @@ var BarChart = ({
5420
5518
  barWidth = 0.8,
5421
5519
  className = "",
5422
5520
  xAxisLabel,
5423
- yAxisLabel
5521
+ yAxisLabel,
5522
+ baseFontSize = 14,
5523
+ colors = defaultColors2
5424
5524
  }) => {
5425
- const height = providedHeight ?? 400;
5426
- const width = providedWidth ?? (responsive ? 800 : 600);
5525
+ const viewBoxWidth = 1e3;
5526
+ const viewBoxHeight = 600;
5527
+ const containerRef = React27.useRef(null);
5528
+ const [tooltipPosition, setTooltipPosition] = React27.useState(null);
5427
5529
  const [hoveredBar, setHoveredBar] = React27.useState(null);
5530
+ const chartId = React27.useId();
5531
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
5532
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
5533
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
5534
+ const barClass = `chart-bar-${chartId.replace(/:/g, "-")}`;
5428
5535
  const padding = {
5429
- top: 20,
5430
- right: 20,
5431
- bottom: showXAxis ? horizontal ? 60 : 80 : 20,
5432
- left: showYAxis ? horizontal ? 80 : 60 : 20
5536
+ top: 50,
5537
+ right: 50,
5538
+ bottom: showXAxis ? horizontal ? 120 : 140 : 50,
5539
+ left: showYAxis ? horizontal ? 140 : 130 : 50
5433
5540
  };
5434
- const chartWidth = width - padding.left - padding.right;
5435
- const chartHeight = height - padding.top - padding.bottom;
5541
+ const chartWidth = viewBoxWidth - padding.left - padding.right;
5542
+ const chartHeight = viewBoxHeight - padding.top - padding.bottom;
5543
+ const gridLabelFontSize = viewBoxWidth * 0.045;
5544
+ const axisLabelFontSize = viewBoxWidth * 0.05;
5545
+ const titleFontSize = viewBoxWidth * 0.055;
5436
5546
  const allYValues = stacked ? data[0]?.data.map(
5437
5547
  (_, i) => data.reduce((sum, series) => sum + (series.data[i]?.y || 0), 0)
5438
5548
  ) || [] : data.flatMap((series) => series.data.map((p) => p.y));
5439
5549
  const minY = Math.min(0, ...allYValues);
5440
5550
  const maxY = Math.max(...allYValues);
5441
5551
  const yRange = maxY - minY;
5442
- const yMin = minY - yRange * 0.1;
5552
+ const yMin = Math.max(0, minY - yRange * 0.1);
5443
5553
  const yMax = maxY + yRange * 0.1;
5444
5554
  const numBars = data[0]?.data.length || 0;
5445
5555
  const numSeries = data.length;
@@ -5466,19 +5576,20 @@ var BarChart = ({
5466
5576
  x2: chartWidth,
5467
5577
  y2: y,
5468
5578
  stroke: "currentColor",
5469
- strokeWidth: "1",
5579
+ strokeWidth: "0.5",
5470
5580
  className: "text-gray-200 dark:text-gray-700",
5471
- strokeDasharray: "2,2"
5581
+ strokeDasharray: "4,4"
5472
5582
  }
5473
5583
  ),
5474
5584
  showYAxis && !horizontal && /* @__PURE__ */ jsx109(
5475
5585
  "text",
5476
5586
  {
5477
- x: -10,
5478
- y: y + 4,
5587
+ x: -25,
5588
+ y,
5479
5589
  textAnchor: "end",
5480
- fontSize: "14",
5481
- className: "fill-gray-600 dark:fill-gray-400",
5590
+ dominantBaseline: "middle",
5591
+ fontSize: gridLabelFontSize,
5592
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5482
5593
  children: yValue.toFixed(0)
5483
5594
  }
5484
5595
  )
@@ -5527,12 +5638,20 @@ var BarChart = ({
5527
5638
  x: xPos,
5528
5639
  y: yPos,
5529
5640
  width: barW,
5530
- height: barHeight,
5531
- fill: data[seriesIndex].color || defaultColors2[seriesIndex % defaultColors2.length],
5532
- className: "cursor-pointer transition-opacity",
5641
+ height: Math.abs(scaleY(0) - yPos),
5642
+ fill: data[seriesIndex].color || colors[seriesIndex % colors.length],
5643
+ className: `cursor-pointer transition-opacity ${barClass}`,
5533
5644
  opacity: isHovered ? 0.8 : 1,
5534
- onMouseEnter: () => showTooltip && setHoveredBar({ seriesIndex, barIndex, x: xPos + barW / 2, y: yPos }),
5535
- onMouseLeave: () => setHoveredBar(null)
5645
+ onMouseEnter: () => {
5646
+ if (showTooltip) {
5647
+ setHoveredBar({ seriesIndex, barIndex, x: xPos + barW / 2, y: yPos });
5648
+ setTooltipPosition(getTooltipPosition(padding.left + xPos + barW / 2, padding.top + yPos));
5649
+ }
5650
+ },
5651
+ onMouseLeave: () => {
5652
+ setHoveredBar(null);
5653
+ setTooltipPosition(null);
5654
+ }
5536
5655
  },
5537
5656
  `bar-${seriesIndex}-${barIndex}`
5538
5657
  )
@@ -5557,8 +5676,8 @@ var BarChart = ({
5557
5676
  y: yPos,
5558
5677
  width: actualBarWidth,
5559
5678
  height: barHeight,
5560
- fill: data[seriesIndex].color || defaultColors2[seriesIndex % defaultColors2.length],
5561
- className: "cursor-pointer transition-opacity",
5679
+ fill: data[seriesIndex].color || colors[seriesIndex % colors.length],
5680
+ className: `cursor-pointer transition-opacity ${barClass}`,
5562
5681
  opacity: isHovered ? 0.8 : 1,
5563
5682
  onMouseEnter: () => showTooltip && setHoveredBar({ seriesIndex, barIndex, x: xPos + actualBarWidth / 2, y: yPos }),
5564
5683
  onMouseLeave: () => setHoveredBar(null)
@@ -5572,10 +5691,11 @@ var BarChart = ({
5572
5691
  "text",
5573
5692
  {
5574
5693
  x: xPos + actualBarWidth / 2,
5575
- y: yPos - 5,
5694
+ y: yPos - 10,
5576
5695
  textAnchor: "middle",
5577
- fontSize: "14",
5578
- fontWeight: "500",
5696
+ dominantBaseline: "middle",
5697
+ fontSize: "11",
5698
+ fontWeight: "600",
5579
5699
  className: "fill-gray-700 dark:fill-gray-300",
5580
5700
  children: point.y
5581
5701
  },
@@ -5594,30 +5714,77 @@ var BarChart = ({
5594
5714
  "text",
5595
5715
  {
5596
5716
  x: xPos,
5597
- y: chartHeight + 20,
5717
+ y: chartHeight + 35,
5598
5718
  textAnchor: "middle",
5599
- fontSize: "14",
5600
- className: "fill-gray-600 dark:fill-gray-400",
5719
+ dominantBaseline: "hanging",
5720
+ fontSize: gridLabelFontSize,
5721
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5601
5722
  children: point.x
5602
5723
  },
5603
5724
  `x-label-${i}`
5604
5725
  );
5605
5726
  });
5727
+ const getTooltipPosition = React27.useCallback((x, y) => {
5728
+ if (!containerRef.current) return { x, y };
5729
+ const rect = containerRef.current.getBoundingClientRect();
5730
+ const tooltipWidth = 140;
5731
+ const tooltipHeight = 80;
5732
+ let tooltipX = x + 10;
5733
+ let tooltipY = y - 30;
5734
+ if (tooltipX + tooltipWidth > rect.width) {
5735
+ tooltipX = x - tooltipWidth - 10;
5736
+ }
5737
+ if (tooltipY + tooltipHeight > rect.height) {
5738
+ tooltipY = y + 30;
5739
+ }
5740
+ return { x: tooltipX, y: tooltipY };
5741
+ }, []);
5742
+ const containerStyle = {
5743
+ "--font-size-base": `${baseFontSize}px`,
5744
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
5745
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
5746
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`
5747
+ };
5606
5748
  return /* @__PURE__ */ jsxs36(
5607
5749
  "div",
5608
5750
  {
5609
- className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
5610
- style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
5751
+ ref: containerRef,
5752
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
5753
+ style: {
5754
+ ...containerStyle
5755
+ },
5611
5756
  children: [
5757
+ /* @__PURE__ */ jsx109("style", { children: `
5758
+ /* Mobile: Large fonts, hidden axis titles, thicker bars (default) */
5759
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
5760
+ .${axisLabelClass} { display: none; }
5761
+
5762
+ /* Tablet: Medium fonts, show axis titles */
5763
+ @media (min-width: 640px) {
5764
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
5765
+ .${axisLabelClass} {
5766
+ font-size: ${axisLabelFontSize * 0.7}px !important;
5767
+ display: block;
5768
+ }
5769
+ }
5770
+
5771
+ /* Desktop: Small fonts, show axis titles */
5772
+ @media (min-width: 1024px) {
5773
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
5774
+ .${axisLabelClass} {
5775
+ font-size: ${axisLabelFontSize * 0.4}px !important;
5776
+ display: block;
5777
+ }
5778
+ }
5779
+ ` }),
5612
5780
  /* @__PURE__ */ jsx109(
5613
5781
  "svg",
5614
5782
  {
5615
5783
  width: "100%",
5616
- height: "100%",
5617
- viewBox: `0 0 ${width} ${height}`,
5784
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
5618
5785
  preserveAspectRatio: "xMidYMid meet",
5619
- className: "bg-white dark:bg-gray-800 block",
5620
- style: { overflow: "visible" },
5786
+ className: "bg-white dark:bg-gray-800 block w-full",
5787
+ style: { height: "auto", overflow: "visible" },
5621
5788
  children: /* @__PURE__ */ jsxs36("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5622
5789
  gridLines,
5623
5790
  renderBars(),
@@ -5626,11 +5793,12 @@ var BarChart = ({
5626
5793
  "text",
5627
5794
  {
5628
5795
  x: chartWidth / 2,
5629
- y: chartHeight + 50,
5796
+ y: chartHeight + 80,
5630
5797
  textAnchor: "middle",
5631
- fontSize: "16",
5632
- fontWeight: "500",
5633
- className: "fill-gray-700 dark:fill-gray-300",
5798
+ dominantBaseline: "hanging",
5799
+ fontSize: axisLabelFontSize,
5800
+ fontWeight: "600",
5801
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5634
5802
  children: xAxisLabel
5635
5803
  }
5636
5804
  ),
@@ -5638,41 +5806,43 @@ var BarChart = ({
5638
5806
  "text",
5639
5807
  {
5640
5808
  x: -chartHeight / 2,
5641
- y: -45,
5809
+ y: -100,
5642
5810
  textAnchor: "middle",
5643
- fontSize: "16",
5644
- fontWeight: "500",
5645
- transform: `rotate(-90, 0, 0)`,
5646
- className: "fill-gray-700 dark:fill-gray-300",
5811
+ dominantBaseline: "middle",
5812
+ fontSize: axisLabelFontSize,
5813
+ fontWeight: "600",
5814
+ transform: "rotate(-90)",
5815
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5647
5816
  children: yAxisLabel
5648
5817
  }
5649
5818
  )
5650
5819
  ] })
5651
5820
  }
5652
5821
  ),
5653
- showLegend && /* @__PURE__ */ jsx109("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-2", children: [
5822
+ showLegend && /* @__PURE__ */ jsx109("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((series, index) => /* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-2 text-sm", children: [
5654
5823
  /* @__PURE__ */ jsx109(
5655
5824
  "div",
5656
5825
  {
5657
- className: "w-4 h-4 rounded-sm",
5826
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
5658
5827
  style: {
5659
- backgroundColor: series.color || defaultColors2[index % defaultColors2.length]
5828
+ backgroundColor: series.color || colors[index % colors.length]
5660
5829
  }
5661
5830
  }
5662
5831
  ),
5663
- /* @__PURE__ */ jsx109("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5832
+ /* @__PURE__ */ jsx109("span", { className: "text-gray-700 dark:text-gray-300", children: series.name })
5664
5833
  ] }, `legend-${index}`)) }),
5665
- showTooltip && hoveredBar && /* @__PURE__ */ jsxs36(
5834
+ showTooltip && hoveredBar && tooltipPosition && /* @__PURE__ */ jsxs36(
5666
5835
  "div",
5667
5836
  {
5668
- 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",
5837
+ 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",
5669
5838
  style: {
5670
- left: `${padding.left + hoveredBar.x + 10}px`,
5671
- top: `${padding.top + hoveredBar.y - 30}px`
5839
+ left: `${tooltipPosition.x}px`,
5840
+ top: `${tooltipPosition.y}px`,
5841
+ transform: "translateZ(0)"
5672
5842
  },
5673
5843
  children: [
5674
5844
  /* @__PURE__ */ jsx109("div", { className: "font-semibold", children: data[hoveredBar.seriesIndex].name }),
5675
- /* @__PURE__ */ jsxs36("div", { children: [
5845
+ /* @__PURE__ */ jsxs36("div", { className: "text-xs opacity-90", children: [
5676
5846
  data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].x,
5677
5847
  ": ",
5678
5848
  data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].y
@@ -5720,14 +5890,32 @@ var AreaChart = ({
5720
5890
  strokeWidth = 2,
5721
5891
  className = "",
5722
5892
  xAxisLabel,
5723
- yAxisLabel
5893
+ yAxisLabel,
5894
+ baseFontSize = 14
5724
5895
  }) => {
5725
- const height = providedHeight ?? 400;
5726
- const width = providedWidth ?? 800;
5896
+ const viewBoxWidth = 1e3;
5897
+ const viewBoxHeight = 600;
5898
+ const containerRef = React28.useRef(null);
5899
+ const svgRef = React28.useRef(null);
5900
+ const [tooltipPosition, setTooltipPosition] = React28.useState(null);
5727
5901
  const [hoveredPoint, setHoveredPoint] = React28.useState(null);
5728
- const padding = { top: 20, right: 20, bottom: showXAxis ? 60 : 20, left: showYAxis ? 60 : 20 };
5729
- const chartWidth = width - padding.left - padding.right;
5730
- const chartHeight = height - padding.top - padding.bottom;
5902
+ const chartId = React28.useId();
5903
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
5904
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
5905
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
5906
+ const lineClass = `chart-line-${chartId.replace(/:/g, "-")}`;
5907
+ const pointClass = `chart-point-${chartId.replace(/:/g, "-")}`;
5908
+ const padding = {
5909
+ top: 50,
5910
+ right: 50,
5911
+ bottom: showXAxis ? 120 : 50,
5912
+ left: showYAxis ? 130 : 50
5913
+ };
5914
+ const chartWidth = viewBoxWidth - padding.left - padding.right;
5915
+ const chartHeight = viewBoxHeight - padding.top - padding.bottom;
5916
+ const gridLabelFontSize = viewBoxWidth * 0.045;
5917
+ const axisLabelFontSize = viewBoxWidth * 0.05;
5918
+ const titleFontSize = viewBoxWidth * 0.055;
5731
5919
  const allPoints = data.flatMap((series) => series.data);
5732
5920
  const allYValues = stacked ? data[0]?.data.map(
5733
5921
  (_, i) => data.reduce((sum, series) => sum + (series.data[i]?.y || 0), 0)
@@ -5741,7 +5929,7 @@ var AreaChart = ({
5741
5929
  const minY = Math.min(0, ...allYValues);
5742
5930
  const maxY = Math.max(...allYValues);
5743
5931
  const yRange = maxY - minY;
5744
- const yMin = minY - yRange * 0.1;
5932
+ const yMin = Math.max(0, minY - yRange * 0.1);
5745
5933
  const yMax = maxY + yRange * 0.1;
5746
5934
  const scaleX = (x, index) => {
5747
5935
  const numX = isStringX ? index : x;
@@ -5822,20 +6010,21 @@ var AreaChart = ({
5822
6010
  x2: chartWidth,
5823
6011
  y2: y,
5824
6012
  stroke: "currentColor",
5825
- strokeWidth: "1",
6013
+ strokeWidth: "0.5",
5826
6014
  className: "text-gray-200 dark:text-gray-700",
5827
- strokeDasharray: "2,2"
6015
+ strokeDasharray: "4,4"
5828
6016
  }
5829
6017
  ),
5830
6018
  showYAxis && /* @__PURE__ */ jsx110(
5831
6019
  "text",
5832
6020
  {
5833
- x: -10,
5834
- y: y + 4,
6021
+ x: -25,
6022
+ y,
5835
6023
  textAnchor: "end",
5836
- fontSize: "12",
5837
- className: "fill-gray-600 dark:fill-gray-400",
5838
- children: yValue.toFixed(0)
6024
+ dominantBaseline: "middle",
6025
+ fontSize: gridLabelFontSize,
6026
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
6027
+ children: yValue.toFixed(1)
5839
6028
  }
5840
6029
  )
5841
6030
  ] }, `grid-h-${i}`)
@@ -5855,19 +6044,20 @@ var AreaChart = ({
5855
6044
  x2: x,
5856
6045
  y2: chartHeight,
5857
6046
  stroke: "currentColor",
5858
- strokeWidth: "1",
6047
+ strokeWidth: "0.5",
5859
6048
  className: "text-gray-200 dark:text-gray-700",
5860
- strokeDasharray: "2,2"
6049
+ strokeDasharray: "4,4"
5861
6050
  }
5862
6051
  ),
5863
6052
  showXAxis && /* @__PURE__ */ jsx110(
5864
6053
  "text",
5865
6054
  {
5866
6055
  x,
5867
- y: chartHeight + 20,
6056
+ y: chartHeight + 35,
5868
6057
  textAnchor: "middle",
5869
- fontSize: "12",
5870
- className: "fill-gray-600 dark:fill-gray-400",
6058
+ dominantBaseline: "hanging",
6059
+ fontSize: gridLabelFontSize,
6060
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
5871
6061
  children: xValue
5872
6062
  }
5873
6063
  )
@@ -5879,20 +6069,72 @@ var AreaChart = ({
5879
6069
  if (stacked) {
5880
6070
  cumulativeValues = Array(data[0]?.data.length || 0).fill(0);
5881
6071
  }
6072
+ const getTooltipPosition = React28.useCallback((x, y) => {
6073
+ if (!containerRef.current) return { x, y };
6074
+ const rect = containerRef.current.getBoundingClientRect();
6075
+ const tooltipWidth = 120;
6076
+ const tooltipHeight = 80;
6077
+ let tooltipX = x + 10;
6078
+ let tooltipY = y - 30;
6079
+ if (tooltipX + tooltipWidth > rect.width) {
6080
+ tooltipX = x - tooltipWidth - 10;
6081
+ }
6082
+ if (tooltipY + tooltipHeight > rect.height) {
6083
+ tooltipY = y + 30;
6084
+ }
6085
+ return { x: tooltipX, y: tooltipY };
6086
+ }, []);
6087
+ const containerStyle = {
6088
+ "--font-size-base": `${baseFontSize}px`,
6089
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
6090
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
6091
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`
6092
+ };
5882
6093
  return /* @__PURE__ */ jsxs37(
5883
6094
  "div",
5884
6095
  {
5885
- className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
5886
- style: responsive ? { width: "100%", aspectRatio: `${width} / ${height}` } : void 0,
6096
+ ref: containerRef,
6097
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
6098
+ style: containerStyle,
5887
6099
  children: [
6100
+ /* @__PURE__ */ jsx110("style", { children: `
6101
+ /* Mobile: Large fonts, hidden axis titles, thicker lines (default) */
6102
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
6103
+ .${axisLabelClass} { display: none; }
6104
+ .${lineClass} { stroke-width: ${strokeWidth * 2.5} !important; }
6105
+ .${pointClass} { r: 6 !important; stroke-width: 3 !important; }
6106
+
6107
+ /* Tablet: Medium fonts, show axis titles, medium lines */
6108
+ @media (min-width: 640px) {
6109
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
6110
+ .${axisLabelClass} {
6111
+ font-size: ${axisLabelFontSize * 0.7}px !important;
6112
+ display: block;
6113
+ }
6114
+ .${lineClass} { stroke-width: ${strokeWidth * 1.5} !important; }
6115
+ .${pointClass} { r: 4 !important; stroke-width: 2 !important; }
6116
+ }
6117
+
6118
+ /* Desktop: Small fonts, show axis titles, normal lines */
6119
+ @media (min-width: 1024px) {
6120
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
6121
+ .${axisLabelClass} {
6122
+ font-size: ${axisLabelFontSize * 0.4}px !important;
6123
+ display: block;
6124
+ }
6125
+ .${lineClass} { stroke-width: ${strokeWidth} !important; }
6126
+ .${pointClass} { r: 3 !important; stroke-width: 1.5 !important; }
6127
+ }
6128
+ ` }),
5888
6129
  /* @__PURE__ */ jsx110(
5889
6130
  "svg",
5890
6131
  {
6132
+ ref: svgRef,
5891
6133
  width: "100%",
5892
- height: "100%",
5893
- viewBox: `0 0 ${width} ${height}`,
6134
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
5894
6135
  preserveAspectRatio: "xMidYMid meet",
5895
- className: "bg-white dark:bg-gray-800 block",
6136
+ className: "bg-white dark:bg-gray-800 block w-full",
6137
+ style: { height: "auto", overflow: "visible" },
5896
6138
  children: /* @__PURE__ */ jsxs37("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5897
6139
  gridLines,
5898
6140
  data.map((series, seriesIndex) => {
@@ -5921,7 +6163,8 @@ var AreaChart = ({
5921
6163
  stroke: series.color || defaultColors3[seriesIndex % defaultColors3.length],
5922
6164
  strokeWidth,
5923
6165
  strokeLinecap: "round",
5924
- strokeLinejoin: "round"
6166
+ strokeLinejoin: "round",
6167
+ className: lineClass
5925
6168
  }
5926
6169
  )
5927
6170
  ] }, `area-${seriesIndex}`);
@@ -5943,9 +6186,28 @@ var AreaChart = ({
5943
6186
  fill: series.color || defaultColors3[seriesIndex % defaultColors3.length],
5944
6187
  stroke: "white",
5945
6188
  strokeWidth: "2",
5946
- className: "cursor-pointer transition-all",
5947
- onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
5948
- onMouseLeave: () => setHoveredPoint(null)
6189
+ className: `cursor-pointer transition-all ${pointClass}`,
6190
+ onMouseEnter: (e) => {
6191
+ if (showTooltip && containerRef.current) {
6192
+ setHoveredPoint({ seriesIndex, pointIndex, x, y });
6193
+ const containerRect = containerRef.current.getBoundingClientRect();
6194
+ const mouseX = e.clientX - containerRect.left;
6195
+ const mouseY = e.clientY - containerRect.top;
6196
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
6197
+ }
6198
+ },
6199
+ onMouseMove: (e) => {
6200
+ if (showTooltip && hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex && containerRef.current) {
6201
+ const containerRect = containerRef.current.getBoundingClientRect();
6202
+ const mouseX = e.clientX - containerRect.left;
6203
+ const mouseY = e.clientY - containerRect.top;
6204
+ setTooltipPosition(getTooltipPosition(mouseX, mouseY));
6205
+ }
6206
+ },
6207
+ onMouseLeave: () => {
6208
+ setHoveredPoint(null);
6209
+ setTooltipPosition(null);
6210
+ }
5949
6211
  },
5950
6212
  `point-${seriesIndex}-${pointIndex}`
5951
6213
  );
@@ -5955,11 +6217,12 @@ var AreaChart = ({
5955
6217
  "text",
5956
6218
  {
5957
6219
  x: chartWidth / 2,
5958
- y: chartHeight + 50,
6220
+ y: chartHeight + 80,
5959
6221
  textAnchor: "middle",
5960
- fontSize: "14",
5961
- fontWeight: "500",
5962
- className: "fill-gray-700 dark:fill-gray-300",
6222
+ dominantBaseline: "hanging",
6223
+ fontSize: axisLabelFontSize,
6224
+ fontWeight: "600",
6225
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5963
6226
  children: xAxisLabel
5964
6227
  }
5965
6228
  ),
@@ -5967,45 +6230,47 @@ var AreaChart = ({
5967
6230
  "text",
5968
6231
  {
5969
6232
  x: -chartHeight / 2,
5970
- y: -45,
6233
+ y: -100,
5971
6234
  textAnchor: "middle",
5972
- fontSize: "14",
5973
- fontWeight: "500",
5974
- transform: "rotate(-90, 0, 0)",
5975
- className: "fill-gray-700 dark:fill-gray-300",
6235
+ dominantBaseline: "middle",
6236
+ fontSize: axisLabelFontSize,
6237
+ fontWeight: "600",
6238
+ transform: "rotate(-90)",
6239
+ className: `fill-gray-700 dark:fill-gray-300 ${axisLabelClass}`,
5976
6240
  children: yAxisLabel
5977
6241
  }
5978
6242
  )
5979
6243
  ] })
5980
6244
  }
5981
6245
  ),
5982
- showLegend && /* @__PURE__ */ jsx110("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-2", children: [
6246
+ showLegend && /* @__PURE__ */ jsx110("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((series, index) => /* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-2 text-sm", children: [
5983
6247
  /* @__PURE__ */ jsx110(
5984
6248
  "div",
5985
6249
  {
5986
- className: "w-4 h-4 rounded-sm",
6250
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
5987
6251
  style: {
5988
6252
  backgroundColor: series.color || defaultColors3[index % defaultColors3.length]
5989
6253
  }
5990
6254
  }
5991
6255
  ),
5992
- /* @__PURE__ */ jsx110("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
6256
+ /* @__PURE__ */ jsx110("span", { className: "text-gray-700 dark:text-gray-300", children: series.name })
5993
6257
  ] }, `legend-${index}`)) }),
5994
- showTooltip && hoveredPoint && /* @__PURE__ */ jsxs37(
6258
+ showTooltip && hoveredPoint && tooltipPosition && /* @__PURE__ */ jsxs37(
5995
6259
  "div",
5996
6260
  {
5997
- 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",
6261
+ 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",
5998
6262
  style: {
5999
- left: `${padding.left + hoveredPoint.x + 10}px`,
6000
- top: `${padding.top + hoveredPoint.y - 30}px`
6263
+ left: `${tooltipPosition.x}px`,
6264
+ top: `${tooltipPosition.y}px`,
6265
+ transform: "translateZ(0)"
6001
6266
  },
6002
6267
  children: [
6003
6268
  /* @__PURE__ */ jsx110("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
6004
- /* @__PURE__ */ jsxs37("div", { children: [
6269
+ /* @__PURE__ */ jsxs37("div", { className: "text-xs opacity-90", children: [
6005
6270
  "x: ",
6006
6271
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
6007
6272
  ] }),
6008
- /* @__PURE__ */ jsxs37("div", { children: [
6273
+ /* @__PURE__ */ jsxs37("div", { className: "text-xs opacity-90", children: [
6009
6274
  "y: ",
6010
6275
  data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
6011
6276
  ] })
@@ -6050,16 +6315,27 @@ var PieChart = ({
6050
6315
  showPercentages = false,
6051
6316
  donut = false,
6052
6317
  donutWidth = 60,
6053
- className = ""
6318
+ className = "",
6319
+ baseFontSize = 14
6054
6320
  }) => {
6055
- const height = providedHeight ?? 400;
6056
- const width = providedWidth ?? 400;
6321
+ const viewBoxWidth = 600;
6322
+ const viewBoxHeight = 600;
6323
+ const containerRef = React29.useRef(null);
6324
+ const [tooltipPosition, setTooltipPosition] = React29.useState(null);
6057
6325
  const [hoveredSlice, setHoveredSlice] = React29.useState(null);
6326
+ const chartId = React29.useId();
6327
+ const wrapperClass = `chart-svg-wrapper-${chartId.replace(/:/g, "-")}`;
6328
+ const gridLabelClass = `chart-grid-label-${chartId.replace(/:/g, "-")}`;
6329
+ const axisLabelClass = `chart-axis-label-${chartId.replace(/:/g, "-")}`;
6330
+ const sliceClass = `chart-slice-${chartId.replace(/:/g, "-")}`;
6058
6331
  const total = data.reduce((sum, item) => sum + item.value, 0);
6059
- const centerX = width / 2;
6060
- const centerY = height / 2;
6061
- const radius = Math.min(width, height) / 2 - 40;
6332
+ const centerX = viewBoxWidth / 2;
6333
+ const centerY = viewBoxHeight / 2;
6334
+ const radius = Math.min(viewBoxWidth, viewBoxHeight) / 2 - 40;
6062
6335
  const innerRadius = donut ? radius - donutWidth : 0;
6336
+ const gridLabelFontSize = viewBoxWidth * 0.045;
6337
+ const axisLabelFontSize = viewBoxWidth * 0.05;
6338
+ const titleFontSize = viewBoxWidth * 0.055;
6063
6339
  let currentAngle = -90;
6064
6340
  const slices = data.map((item, index) => {
6065
6341
  const percentage = item.value / total * 100;
@@ -6111,20 +6387,64 @@ var PieChart = ({
6111
6387
  index
6112
6388
  };
6113
6389
  });
6390
+ const getTooltipPosition = React29.useCallback((x, y) => {
6391
+ if (!containerRef.current) return { x, y };
6392
+ const rect = containerRef.current.getBoundingClientRect();
6393
+ const tooltipWidth = 120;
6394
+ const tooltipHeight = 80;
6395
+ let tooltipX = x + 10;
6396
+ let tooltipY = y - 30;
6397
+ if (tooltipX + tooltipWidth > rect.width) {
6398
+ tooltipX = x - tooltipWidth - 10;
6399
+ }
6400
+ if (tooltipY + tooltipHeight > rect.height) {
6401
+ tooltipY = y + 30;
6402
+ }
6403
+ return { x: tooltipX, y: tooltipY };
6404
+ }, []);
6405
+ const containerStyle = {
6406
+ "--font-size-base": `${baseFontSize}px`,
6407
+ "--font-size-lg": `calc(var(--font-size-base) * 1.125)`,
6408
+ "--font-size-sm": `calc(var(--font-size-base) * 0.875)`,
6409
+ "--font-size-xs": `calc(var(--font-size-base) * 0.75)`,
6410
+ "--font-size-xl": `calc(var(--font-size-base) * 1.5)`,
6411
+ "--font-size-2xl": `calc(var(--font-size-base) * 2)`
6412
+ };
6413
+ if (responsive) {
6414
+ containerStyle["--font-size-base"] = `clamp(${baseFontSize * 0.8}px, 4vw, ${baseFontSize}px)`;
6415
+ }
6114
6416
  return /* @__PURE__ */ jsxs38(
6115
6417
  "div",
6116
6418
  {
6117
- className: `relative ${responsive ? "w-full flex justify-center" : "inline-block"} ${className}`,
6118
- style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
6419
+ ref: containerRef,
6420
+ className: `relative flex flex-col gap-4 ${responsive ? "w-full" : "inline-block"} ${className}`,
6421
+ style: containerStyle,
6119
6422
  children: [
6423
+ /* @__PURE__ */ jsx111("style", { children: `
6424
+ /* Mobile: Large fonts (default) */
6425
+ .${gridLabelClass} { font-size: ${gridLabelFontSize}px !important; }
6426
+ .${axisLabelClass} { font-size: ${titleFontSize}px !important; }
6427
+
6428
+ /* Tablet: Medium fonts */
6429
+ @media (min-width: 640px) {
6430
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.7}px !important; }
6431
+ .${axisLabelClass} { font-size: ${titleFontSize * 0.7}px !important; }
6432
+ }
6433
+
6434
+ /* Desktop: Small fonts */
6435
+ @media (min-width: 1024px) {
6436
+ .${gridLabelClass} { font-size: ${gridLabelFontSize * 0.4}px !important; }
6437
+ .${axisLabelClass} { font-size: ${titleFontSize * 0.4}px !important; }
6438
+ }
6439
+ ` }),
6120
6440
  /* @__PURE__ */ jsxs38(
6121
6441
  "svg",
6122
6442
  {
6123
6443
  width: "100%",
6124
- height: "100%",
6125
- viewBox: `0 0 ${width} ${height}`,
6444
+ viewBox: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
6126
6445
  preserveAspectRatio: "xMidYMid meet",
6127
- className: "bg-white dark:bg-gray-800 block",
6446
+ className: "bg-white dark:bg-gray-800 block w-full",
6447
+ style: { height: "auto", overflow: "visible" },
6128
6448
  children: [
6129
6449
  slices.map((slice) => {
6130
6450
  const isHovered = hoveredSlice === slice.index;
@@ -6138,8 +6458,19 @@ var PieChart = ({
6138
6458
  strokeWidth: "2",
6139
6459
  className: "cursor-pointer transition-opacity",
6140
6460
  opacity: isHovered ? 0.8 : 1,
6141
- onMouseEnter: () => setHoveredSlice(slice.index),
6142
- onMouseLeave: () => setHoveredSlice(null)
6461
+ onMouseEnter: (e) => {
6462
+ setHoveredSlice(slice.index);
6463
+ if (containerRef.current) {
6464
+ const rect = containerRef.current.getBoundingClientRect();
6465
+ const svgX = e.clientX - rect.left;
6466
+ const svgY = e.clientY - rect.top;
6467
+ setTooltipPosition(getTooltipPosition(svgX, svgY));
6468
+ }
6469
+ },
6470
+ onMouseLeave: () => {
6471
+ setHoveredSlice(null);
6472
+ setTooltipPosition(null);
6473
+ }
6143
6474
  }
6144
6475
  ),
6145
6476
  showLabels && slice.percentage > 5 && /* @__PURE__ */ jsxs38(
@@ -6149,9 +6480,9 @@ var PieChart = ({
6149
6480
  y: slice.labelY,
6150
6481
  textAnchor: "middle",
6151
6482
  dominantBaseline: "middle",
6152
- fontSize: "14",
6483
+ fontSize: gridLabelFontSize,
6153
6484
  fontWeight: "600",
6154
- className: "fill-gray-700 dark:fill-gray-200 pointer-events-none",
6485
+ className: `fill-gray-700 dark:fill-gray-200 pointer-events-none ${gridLabelClass}`,
6155
6486
  children: [
6156
6487
  showPercentages && `${slice.percentage.toFixed(1)}%`,
6157
6488
  showPercentages && showValues && " ",
@@ -6169,9 +6500,10 @@ var PieChart = ({
6169
6500
  x: centerX,
6170
6501
  y: centerY - 10,
6171
6502
  textAnchor: "middle",
6172
- fontSize: "32",
6503
+ dominantBaseline: "middle",
6504
+ fontSize: titleFontSize,
6173
6505
  fontWeight: "700",
6174
- className: "fill-gray-900 dark:fill-gray-100",
6506
+ className: `fill-gray-900 dark:fill-gray-100 ${axisLabelClass}`,
6175
6507
  children: total
6176
6508
  }
6177
6509
  ),
@@ -6181,8 +6513,9 @@ var PieChart = ({
6181
6513
  x: centerX,
6182
6514
  y: centerY + 15,
6183
6515
  textAnchor: "middle",
6184
- fontSize: "16",
6185
- className: "fill-gray-600 dark:fill-gray-400",
6516
+ dominantBaseline: "middle",
6517
+ fontSize: axisLabelFontSize,
6518
+ className: `fill-gray-600 dark:fill-gray-400 ${gridLabelClass}`,
6186
6519
  children: "Total"
6187
6520
  }
6188
6521
  )
@@ -6190,23 +6523,23 @@ var PieChart = ({
6190
6523
  ]
6191
6524
  }
6192
6525
  ),
6193
- showLegend && /* @__PURE__ */ jsx111("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((item, index) => /* @__PURE__ */ jsxs38(
6526
+ showLegend && /* @__PURE__ */ jsx111("div", { className: "flex flex-wrap gap-3 justify-center px-4", children: data.map((item, index) => /* @__PURE__ */ jsxs38(
6194
6527
  "div",
6195
6528
  {
6196
- className: "flex items-center gap-2 cursor-pointer",
6529
+ className: "flex items-center gap-2 text-sm cursor-pointer",
6197
6530
  onMouseEnter: () => setHoveredSlice(index),
6198
6531
  onMouseLeave: () => setHoveredSlice(null),
6199
6532
  children: [
6200
6533
  /* @__PURE__ */ jsx111(
6201
6534
  "div",
6202
6535
  {
6203
- className: "w-4 h-4 rounded-sm",
6536
+ className: "w-3 h-3 rounded-sm flex-shrink-0",
6204
6537
  style: {
6205
6538
  backgroundColor: item.color || defaultColors4[index % defaultColors4.length]
6206
6539
  }
6207
6540
  }
6208
6541
  ),
6209
- /* @__PURE__ */ jsxs38("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: [
6542
+ /* @__PURE__ */ jsxs38("span", { className: "text-gray-700 dark:text-gray-300", children: [
6210
6543
  item.label,
6211
6544
  ": ",
6212
6545
  item.value,
@@ -6216,18 +6549,29 @@ var PieChart = ({
6216
6549
  },
6217
6550
  `legend-${index}`
6218
6551
  )) }),
6219
- hoveredSlice !== null && /* @__PURE__ */ jsxs38("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: [
6220
- /* @__PURE__ */ jsx111("div", { className: "font-semibold", children: data[hoveredSlice].label }),
6221
- /* @__PURE__ */ jsxs38("div", { children: [
6222
- "Value: ",
6223
- data[hoveredSlice].value
6224
- ] }),
6225
- /* @__PURE__ */ jsxs38("div", { children: [
6226
- "Percentage: ",
6227
- (data[hoveredSlice].value / total * 100).toFixed(1),
6228
- "%"
6229
- ] })
6230
- ] })
6552
+ hoveredSlice !== null && tooltipPosition && /* @__PURE__ */ jsxs38(
6553
+ "div",
6554
+ {
6555
+ 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",
6556
+ style: {
6557
+ left: `${tooltipPosition.x}px`,
6558
+ top: `${tooltipPosition.y}px`,
6559
+ transform: "translateZ(0)"
6560
+ },
6561
+ children: [
6562
+ /* @__PURE__ */ jsx111("div", { className: "font-semibold", children: data[hoveredSlice].label }),
6563
+ /* @__PURE__ */ jsxs38("div", { className: "text-xs opacity-90", children: [
6564
+ "Value: ",
6565
+ data[hoveredSlice].value
6566
+ ] }),
6567
+ /* @__PURE__ */ jsxs38("div", { className: "text-xs opacity-90", children: [
6568
+ "Percentage: ",
6569
+ (data[hoveredSlice].value / total * 100).toFixed(1),
6570
+ "%"
6571
+ ] })
6572
+ ]
6573
+ }
6574
+ )
6231
6575
  ]
6232
6576
  }
6233
6577
  );