@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.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +529 -185
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +529 -185
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
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
|
|
5155
|
-
const
|
|
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
|
|
5158
|
-
const
|
|
5159
|
-
const
|
|
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: "
|
|
5237
|
+
strokeWidth: "0.5",
|
|
5220
5238
|
className: "text-gray-200 dark:text-gray-700",
|
|
5221
|
-
strokeDasharray: "
|
|
5239
|
+
strokeDasharray: "4,4"
|
|
5222
5240
|
}
|
|
5223
5241
|
),
|
|
5224
5242
|
showYAxis && /* @__PURE__ */ jsx108(
|
|
5225
5243
|
"text",
|
|
5226
5244
|
{
|
|
5227
|
-
x: -
|
|
5228
|
-
y
|
|
5245
|
+
x: -25,
|
|
5246
|
+
y,
|
|
5229
5247
|
textAnchor: "end",
|
|
5230
|
-
|
|
5231
|
-
|
|
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
|
|
5241
|
-
const
|
|
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: "
|
|
5273
|
+
strokeWidth: "0.5",
|
|
5253
5274
|
className: "text-gray-200 dark:text-gray-700",
|
|
5254
|
-
strokeDasharray: "
|
|
5275
|
+
strokeDasharray: "4,4"
|
|
5255
5276
|
}
|
|
5256
5277
|
),
|
|
5257
5278
|
showXAxis && /* @__PURE__ */ jsx108(
|
|
5258
5279
|
"text",
|
|
5259
5280
|
{
|
|
5260
5281
|
x,
|
|
5261
|
-
y: chartHeight +
|
|
5282
|
+
y: chartHeight + 35,
|
|
5262
5283
|
textAnchor: "middle",
|
|
5263
|
-
|
|
5264
|
-
|
|
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
|
-
|
|
5276
|
-
|
|
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
|
-
|
|
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 ?
|
|
5387
|
+
r: isHovered ? 5 : 3,
|
|
5312
5388
|
fill: series.color || defaultColors[seriesIndex % defaultColors.length],
|
|
5313
5389
|
stroke: "white",
|
|
5314
|
-
strokeWidth: "
|
|
5315
|
-
className:
|
|
5316
|
-
onMouseEnter: () =>
|
|
5317
|
-
|
|
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 +
|
|
5422
|
+
y: chartHeight + 80,
|
|
5328
5423
|
textAnchor: "middle",
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
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: -
|
|
5435
|
+
y: -100,
|
|
5340
5436
|
textAnchor: "middle",
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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: `${
|
|
5369
|
-
top: `${
|
|
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
|
|
5426
|
-
const
|
|
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:
|
|
5430
|
-
right:
|
|
5431
|
-
bottom: showXAxis ? horizontal ?
|
|
5432
|
-
left: showYAxis ? horizontal ?
|
|
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 =
|
|
5435
|
-
const chartHeight =
|
|
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: "
|
|
5579
|
+
strokeWidth: "0.5",
|
|
5470
5580
|
className: "text-gray-200 dark:text-gray-700",
|
|
5471
|
-
strokeDasharray: "
|
|
5581
|
+
strokeDasharray: "4,4"
|
|
5472
5582
|
}
|
|
5473
5583
|
),
|
|
5474
5584
|
showYAxis && !horizontal && /* @__PURE__ */ jsx109(
|
|
5475
5585
|
"text",
|
|
5476
5586
|
{
|
|
5477
|
-
x: -
|
|
5478
|
-
y
|
|
5587
|
+
x: -25,
|
|
5588
|
+
y,
|
|
5479
5589
|
textAnchor: "end",
|
|
5480
|
-
|
|
5481
|
-
|
|
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:
|
|
5531
|
-
fill: data[seriesIndex].color ||
|
|
5532
|
-
className:
|
|
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: () =>
|
|
5535
|
-
|
|
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 ||
|
|
5561
|
-
className:
|
|
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 -
|
|
5694
|
+
y: yPos - 10,
|
|
5576
5695
|
textAnchor: "middle",
|
|
5577
|
-
|
|
5578
|
-
|
|
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 +
|
|
5717
|
+
y: chartHeight + 35,
|
|
5598
5718
|
textAnchor: "middle",
|
|
5599
|
-
|
|
5600
|
-
|
|
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
|
-
|
|
5610
|
-
|
|
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
|
-
|
|
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 +
|
|
5796
|
+
y: chartHeight + 80,
|
|
5630
5797
|
textAnchor: "middle",
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
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: -
|
|
5809
|
+
y: -100,
|
|
5642
5810
|
textAnchor: "middle",
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
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-
|
|
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-
|
|
5826
|
+
className: "w-3 h-3 rounded-sm flex-shrink-0",
|
|
5658
5827
|
style: {
|
|
5659
|
-
backgroundColor: series.color ||
|
|
5828
|
+
backgroundColor: series.color || colors[index % colors.length]
|
|
5660
5829
|
}
|
|
5661
5830
|
}
|
|
5662
5831
|
),
|
|
5663
|
-
/* @__PURE__ */ jsx109("span", { className: "text-
|
|
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
|
|
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: `${
|
|
5671
|
-
top: `${
|
|
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
|
|
5726
|
-
const
|
|
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
|
|
5729
|
-
const
|
|
5730
|
-
const
|
|
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: "
|
|
6013
|
+
strokeWidth: "0.5",
|
|
5826
6014
|
className: "text-gray-200 dark:text-gray-700",
|
|
5827
|
-
strokeDasharray: "
|
|
6015
|
+
strokeDasharray: "4,4"
|
|
5828
6016
|
}
|
|
5829
6017
|
),
|
|
5830
6018
|
showYAxis && /* @__PURE__ */ jsx110(
|
|
5831
6019
|
"text",
|
|
5832
6020
|
{
|
|
5833
|
-
x: -
|
|
5834
|
-
y
|
|
6021
|
+
x: -25,
|
|
6022
|
+
y,
|
|
5835
6023
|
textAnchor: "end",
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
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: "
|
|
6047
|
+
strokeWidth: "0.5",
|
|
5859
6048
|
className: "text-gray-200 dark:text-gray-700",
|
|
5860
|
-
strokeDasharray: "
|
|
6049
|
+
strokeDasharray: "4,4"
|
|
5861
6050
|
}
|
|
5862
6051
|
),
|
|
5863
6052
|
showXAxis && /* @__PURE__ */ jsx110(
|
|
5864
6053
|
"text",
|
|
5865
6054
|
{
|
|
5866
6055
|
x,
|
|
5867
|
-
y: chartHeight +
|
|
6056
|
+
y: chartHeight + 35,
|
|
5868
6057
|
textAnchor: "middle",
|
|
5869
|
-
|
|
5870
|
-
|
|
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
|
-
|
|
5886
|
-
|
|
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
|
-
|
|
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:
|
|
5947
|
-
onMouseEnter: () =>
|
|
5948
|
-
|
|
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 +
|
|
6220
|
+
y: chartHeight + 80,
|
|
5959
6221
|
textAnchor: "middle",
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
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: -
|
|
6233
|
+
y: -100,
|
|
5971
6234
|
textAnchor: "middle",
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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: `${
|
|
6000
|
-
top: `${
|
|
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
|
|
6056
|
-
const
|
|
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 =
|
|
6060
|
-
const centerY =
|
|
6061
|
-
const radius = Math.min(
|
|
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
|
-
|
|
6118
|
-
|
|
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
|
-
|
|
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: () =>
|
|
6142
|
-
|
|
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:
|
|
6483
|
+
fontSize: gridLabelFontSize,
|
|
6153
6484
|
fontWeight: "600",
|
|
6154
|
-
className:
|
|
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
|
-
|
|
6503
|
+
dominantBaseline: "middle",
|
|
6504
|
+
fontSize: titleFontSize,
|
|
6173
6505
|
fontWeight: "700",
|
|
6174
|
-
className:
|
|
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
|
-
|
|
6185
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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(
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
"
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
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
|
);
|