@marcoschwartz/lite-ui 0.11.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3333,6 +3333,7 @@ var RichTextEditor = ({
3333
3333
  const [showImageModal, setShowImageModal] = (0, import_react20.useState)(false);
3334
3334
  const [imageUrl, setImageUrl] = (0, import_react20.useState)("");
3335
3335
  const [imageAlt, setImageAlt] = (0, import_react20.useState)("");
3336
+ const savedSelection = (0, import_react20.useRef)(null);
3336
3337
  (0, import_react20.useLayoutEffect)(() => {
3337
3338
  const styleId = "rich-text-editor-styles";
3338
3339
  if (!document.getElementById(styleId)) {
@@ -3359,6 +3360,15 @@ var RichTextEditor = ({
3359
3360
  font-weight: bold;
3360
3361
  margin: 0.83em 0;
3361
3362
  }
3363
+ [contenteditable] p {
3364
+ margin: 0.5em 0;
3365
+ }
3366
+ [contenteditable] p:first-child {
3367
+ margin-top: 0;
3368
+ }
3369
+ [contenteditable] p:last-child {
3370
+ margin-bottom: 0;
3371
+ }
3362
3372
  [contenteditable] ul, [contenteditable] ol {
3363
3373
  margin: 1em 0;
3364
3374
  padding-left: 2em;
@@ -3387,11 +3397,60 @@ var RichTextEditor = ({
3387
3397
  }
3388
3398
  }, []);
3389
3399
  const isInitialRender = (0, import_react20.useRef)(true);
3400
+ const isInternalUpdate = (0, import_react20.useRef)(false);
3390
3401
  (0, import_react20.useEffect)(() => {
3391
- if (!isInitialRender.current && editorRef.current && editorRef.current.innerHTML !== value) {
3402
+ if (isInitialRender.current && editorRef.current) {
3392
3403
  editorRef.current.innerHTML = value;
3404
+ isInitialRender.current = false;
3405
+ try {
3406
+ document.execCommand("defaultParagraphSeparator", false, "p");
3407
+ } catch (e) {
3408
+ console.warn("Could not set defaultParagraphSeparator", e);
3409
+ }
3393
3410
  }
3394
- isInitialRender.current = false;
3411
+ }, []);
3412
+ (0, import_react20.useEffect)(() => {
3413
+ if (!isInitialRender.current && !isInternalUpdate.current && editorRef.current) {
3414
+ const currentHtml = editorRef.current.innerHTML;
3415
+ if (currentHtml !== value) {
3416
+ const selection = window.getSelection();
3417
+ const range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
3418
+ const preSelectionRange = range ? range.cloneRange() : null;
3419
+ if (preSelectionRange && editorRef.current.contains(preSelectionRange.startContainer)) {
3420
+ preSelectionRange.selectNodeContents(editorRef.current);
3421
+ preSelectionRange.setEnd(range.startContainer, range.startOffset);
3422
+ const start = preSelectionRange.toString().length;
3423
+ editorRef.current.innerHTML = value;
3424
+ const textNodes = [];
3425
+ const getTextNodes = (node) => {
3426
+ if (node.nodeType === Node.TEXT_NODE) {
3427
+ textNodes.push(node);
3428
+ } else {
3429
+ node.childNodes.forEach(getTextNodes);
3430
+ }
3431
+ };
3432
+ getTextNodes(editorRef.current);
3433
+ let charCount = 0;
3434
+ let foundStart = false;
3435
+ for (const textNode of textNodes) {
3436
+ const textLength = textNode.textContent?.length || 0;
3437
+ if (!foundStart && charCount + textLength >= start) {
3438
+ const newRange = document.createRange();
3439
+ newRange.setStart(textNode, start - charCount);
3440
+ newRange.collapse(true);
3441
+ selection?.removeAllRanges();
3442
+ selection?.addRange(newRange);
3443
+ foundStart = true;
3444
+ break;
3445
+ }
3446
+ charCount += textLength;
3447
+ }
3448
+ } else {
3449
+ editorRef.current.innerHTML = value;
3450
+ }
3451
+ }
3452
+ }
3453
+ isInternalUpdate.current = false;
3395
3454
  }, [value]);
3396
3455
  const updateActiveFormats = (0, import_react20.useCallback)(() => {
3397
3456
  const formats = /* @__PURE__ */ new Set();
@@ -3412,10 +3471,25 @@ var RichTextEditor = ({
3412
3471
  }, []);
3413
3472
  const handleInput = (0, import_react20.useCallback)(() => {
3414
3473
  if (editorRef.current && onChange) {
3474
+ isInternalUpdate.current = true;
3415
3475
  onChange(editorRef.current.innerHTML);
3416
3476
  }
3417
3477
  updateActiveFormats();
3418
3478
  }, [onChange, updateActiveFormats]);
3479
+ const handleFocus = (0, import_react20.useCallback)(() => {
3480
+ setIsFocused(true);
3481
+ if (editorRef.current && (!editorRef.current.innerHTML || editorRef.current.innerHTML === "")) {
3482
+ editorRef.current.innerHTML = "<p><br></p>";
3483
+ const selection = window.getSelection();
3484
+ const range = document.createRange();
3485
+ if (editorRef.current.firstChild) {
3486
+ range.setStart(editorRef.current.firstChild, 0);
3487
+ range.collapse(true);
3488
+ selection?.removeAllRanges();
3489
+ selection?.addRange(range);
3490
+ }
3491
+ }
3492
+ }, []);
3419
3493
  const handleFormat = (0, import_react20.useCallback)((command) => {
3420
3494
  if (disabled) return;
3421
3495
  document.execCommand(command, false);
@@ -3439,16 +3513,29 @@ var RichTextEditor = ({
3439
3513
  }, [disabled, updateActiveFormats, handleInput]);
3440
3514
  const handleLink = (0, import_react20.useCallback)(() => {
3441
3515
  if (disabled) return;
3516
+ const selection = window.getSelection();
3517
+ if (selection && selection.rangeCount > 0) {
3518
+ savedSelection.current = selection.getRangeAt(0).cloneRange();
3519
+ }
3442
3520
  setShowLinkModal(true);
3443
3521
  }, [disabled]);
3444
3522
  const insertLink = (0, import_react20.useCallback)(() => {
3445
- if (linkUrl) {
3446
- document.execCommand("createLink", false, linkUrl);
3447
- setShowLinkModal(false);
3448
- setLinkUrl("");
3449
- editorRef.current?.focus();
3450
- handleInput();
3523
+ if (!linkUrl || !editorRef.current) return;
3524
+ const selection = window.getSelection();
3525
+ if (savedSelection.current && selection) {
3526
+ try {
3527
+ selection.removeAllRanges();
3528
+ selection.addRange(savedSelection.current);
3529
+ document.execCommand("createLink", false, linkUrl);
3530
+ savedSelection.current = null;
3531
+ } catch (e) {
3532
+ console.warn("Could not insert link at saved position", e);
3533
+ }
3451
3534
  }
3535
+ setShowLinkModal(false);
3536
+ setLinkUrl("");
3537
+ editorRef.current?.focus();
3538
+ handleInput();
3452
3539
  }, [linkUrl, handleInput]);
3453
3540
  const handleCode = (0, import_react20.useCallback)(() => {
3454
3541
  if (disabled) return;
@@ -3468,33 +3555,82 @@ var RichTextEditor = ({
3468
3555
  }, [disabled, handleInput]);
3469
3556
  const handleImage = (0, import_react20.useCallback)(() => {
3470
3557
  if (disabled) return;
3558
+ const selection = window.getSelection();
3559
+ if (selection && selection.rangeCount > 0) {
3560
+ savedSelection.current = selection.getRangeAt(0).cloneRange();
3561
+ }
3471
3562
  setShowImageModal(true);
3472
3563
  }, [disabled]);
3473
3564
  const insertImage = (0, import_react20.useCallback)(() => {
3474
- if (!imageUrl) return;
3565
+ if (!imageUrl || !editorRef.current) return;
3566
+ editorRef.current.focus();
3475
3567
  const img = document.createElement("img");
3476
3568
  img.src = imageUrl;
3477
3569
  img.alt = imageAlt || "";
3478
3570
  img.style.maxWidth = "100%";
3479
3571
  img.style.height = "auto";
3480
3572
  const selection = window.getSelection();
3481
- if (selection && selection.rangeCount > 0) {
3482
- const range = selection.getRangeAt(0);
3483
- range.deleteContents();
3484
- range.insertNode(img);
3485
- range.setStartAfter(img);
3486
- range.setEndAfter(img);
3487
- selection.removeAllRanges();
3488
- selection.addRange(range);
3489
- } else if (editorRef.current) {
3490
- editorRef.current.appendChild(img);
3573
+ if (savedSelection.current && selection && editorRef.current.contains(savedSelection.current.commonAncestorContainer)) {
3574
+ try {
3575
+ selection.removeAllRanges();
3576
+ selection.addRange(savedSelection.current);
3577
+ savedSelection.current.deleteContents();
3578
+ savedSelection.current.insertNode(img);
3579
+ const br = document.createElement("br");
3580
+ savedSelection.current.setStartAfter(img);
3581
+ savedSelection.current.insertNode(br);
3582
+ savedSelection.current.setStartAfter(br);
3583
+ savedSelection.current.collapse(true);
3584
+ selection.removeAllRanges();
3585
+ selection.addRange(savedSelection.current);
3586
+ savedSelection.current = null;
3587
+ } catch (e) {
3588
+ console.warn("Could not insert at saved position", e);
3589
+ if (selection.rangeCount > 0) {
3590
+ const range = selection.getRangeAt(0);
3591
+ if (editorRef.current.contains(range.commonAncestorContainer)) {
3592
+ range.insertNode(img);
3593
+ const br = document.createElement("br");
3594
+ range.setStartAfter(img);
3595
+ range.insertNode(br);
3596
+ range.setStartAfter(br);
3597
+ range.collapse(true);
3598
+ } else {
3599
+ editorRef.current.appendChild(img);
3600
+ editorRef.current.appendChild(document.createElement("br"));
3601
+ }
3602
+ } else {
3603
+ editorRef.current.appendChild(img);
3604
+ editorRef.current.appendChild(document.createElement("br"));
3605
+ }
3606
+ }
3607
+ } else {
3608
+ if (selection && selection.rangeCount > 0) {
3609
+ const range = selection.getRangeAt(0);
3610
+ if (editorRef.current.contains(range.commonAncestorContainer)) {
3611
+ range.deleteContents();
3612
+ range.insertNode(img);
3613
+ const br = document.createElement("br");
3614
+ range.setStartAfter(img);
3615
+ range.insertNode(br);
3616
+ range.setStartAfter(br);
3617
+ range.collapse(true);
3618
+ selection.removeAllRanges();
3619
+ selection.addRange(range);
3620
+ } else {
3621
+ editorRef.current.appendChild(img);
3622
+ editorRef.current.appendChild(document.createElement("br"));
3623
+ }
3624
+ } else {
3625
+ editorRef.current.appendChild(img);
3626
+ editorRef.current.appendChild(document.createElement("br"));
3627
+ }
3491
3628
  }
3492
3629
  setShowImageModal(false);
3493
3630
  setImageUrl("");
3494
3631
  setImageAlt("");
3495
- editorRef.current?.focus();
3496
3632
  handleInput();
3497
- }, [imageUrl, imageAlt, handleInput, disabled]);
3633
+ }, [imageUrl, imageAlt, handleInput]);
3498
3634
  const getButtonClass = (isActive) => {
3499
3635
  const baseClass = themeName === "minimalistic" ? "border border-white text-white transition-colors" : "border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 transition-colors";
3500
3636
  const activeClass = themeName === "minimalistic" ? "bg-white text-black" : "bg-blue-100 dark:bg-blue-900 border-blue-500 dark:border-blue-400";
@@ -3658,11 +3794,10 @@ var RichTextEditor = ({
3658
3794
  ref: editorRef,
3659
3795
  contentEditable: !disabled,
3660
3796
  onInput: handleInput,
3661
- onFocus: () => setIsFocused(true),
3797
+ onFocus: handleFocus,
3662
3798
  onBlur: () => setIsFocused(false),
3663
3799
  onMouseUp: updateActiveFormats,
3664
3800
  onKeyUp: updateActiveFormats,
3665
- dangerouslySetInnerHTML: { __html: value },
3666
3801
  className: `
3667
3802
  w-full px-4 py-3 rounded-b-lg outline-none overflow-y-auto
3668
3803
  ${editorBaseClass} ${focusClass} ${errorClass}
@@ -5151,8 +5286,10 @@ var defaultColors = [
5151
5286
  ];
5152
5287
  var LineChart = ({
5153
5288
  data,
5154
- width = 600,
5155
- height = 400,
5289
+ width: providedWidth,
5290
+ height: providedHeight,
5291
+ aspectRatio = 16 / 9,
5292
+ responsive = true,
5156
5293
  showGrid = true,
5157
5294
  showXAxis = true,
5158
5295
  showYAxis = true,
@@ -5165,6 +5302,8 @@ var LineChart = ({
5165
5302
  xAxisLabel,
5166
5303
  yAxisLabel
5167
5304
  }) => {
5305
+ const height = providedHeight ?? 400;
5306
+ const width = providedWidth ?? (responsive ? 600 : 600);
5168
5307
  const [hoveredPoint, setHoveredPoint] = import_react26.default.useState(null);
5169
5308
  const padding = { top: 20, right: 20, bottom: showXAxis ? 60 : 20, left: showYAxis ? 60 : 20 };
5170
5309
  const chartWidth = width - padding.left - padding.right;
@@ -5239,7 +5378,8 @@ var LineChart = ({
5239
5378
  x: -10,
5240
5379
  y: y + 4,
5241
5380
  textAnchor: "end",
5242
- className: "text-xs fill-gray-600 dark:fill-gray-400",
5381
+ fontSize: "16",
5382
+ className: "fill-gray-600 dark:fill-gray-400",
5243
5383
  children: yValue.toFixed(1)
5244
5384
  }
5245
5385
  )
@@ -5271,7 +5411,8 @@ var LineChart = ({
5271
5411
  x,
5272
5412
  y: chartHeight + 20,
5273
5413
  textAnchor: "middle",
5274
- className: "text-xs fill-gray-600 dark:fill-gray-400",
5414
+ fontSize: "14",
5415
+ className: "fill-gray-600 dark:fill-gray-400",
5275
5416
  children: xValue
5276
5417
  }
5277
5418
  )
@@ -5279,108 +5420,121 @@ var LineChart = ({
5279
5420
  );
5280
5421
  }
5281
5422
  }
5282
- return /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { className: `relative inline-block ${className}`, children: [
5283
- /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5284
- "svg",
5285
- {
5286
- width,
5287
- height,
5288
- className: "bg-white dark:bg-gray-800",
5289
- style: { overflow: "visible" },
5290
- children: /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5291
- gridLines,
5292
- data.map((series, seriesIndex) => /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5293
- "path",
5294
- {
5295
- d: generatePath(series),
5296
- fill: "none",
5297
- stroke: series.color || defaultColors[seriesIndex % defaultColors.length],
5298
- strokeWidth,
5299
- strokeLinecap: "round",
5300
- strokeLinejoin: "round"
5301
- },
5302
- `line-${seriesIndex}`
5303
- )),
5304
- showDots && data.map(
5305
- (series, seriesIndex) => series.data.map((point, pointIndex) => {
5306
- const x = scaleX(point.x, pointIndex);
5307
- const y = scaleY(point.y);
5308
- const isHovered = hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex;
5309
- return /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5310
- "circle",
5423
+ return /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)(
5424
+ "div",
5425
+ {
5426
+ className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
5427
+ style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
5428
+ children: [
5429
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5430
+ "svg",
5431
+ {
5432
+ width: "100%",
5433
+ height: "100%",
5434
+ viewBox: `0 0 ${width} ${height}`,
5435
+ preserveAspectRatio: "xMidYMid meet",
5436
+ className: "bg-white dark:bg-gray-800 block",
5437
+ style: { overflow: "visible" },
5438
+ children: /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5439
+ gridLines,
5440
+ data.map((series, seriesIndex) => /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5441
+ "path",
5311
5442
  {
5312
- cx: x,
5313
- cy: y,
5314
- r: isHovered ? 6 : 4,
5315
- fill: series.color || defaultColors[seriesIndex % defaultColors.length],
5316
- stroke: "white",
5317
- strokeWidth: "2",
5318
- className: "cursor-pointer transition-all",
5319
- onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
5320
- onMouseLeave: () => setHoveredPoint(null)
5443
+ d: generatePath(series),
5444
+ fill: "none",
5445
+ stroke: series.color || defaultColors[seriesIndex % defaultColors.length],
5446
+ strokeWidth,
5447
+ strokeLinecap: "round",
5448
+ strokeLinejoin: "round"
5321
5449
  },
5322
- `point-${seriesIndex}-${pointIndex}`
5323
- );
5324
- })
5325
- ),
5326
- xAxisLabel && showXAxis && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5327
- "text",
5450
+ `line-${seriesIndex}`
5451
+ )),
5452
+ showDots && data.map(
5453
+ (series, seriesIndex) => series.data.map((point, pointIndex) => {
5454
+ const x = scaleX(point.x, pointIndex);
5455
+ const y = scaleY(point.y);
5456
+ const isHovered = hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex;
5457
+ return /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5458
+ "circle",
5459
+ {
5460
+ cx: x,
5461
+ cy: y,
5462
+ r: isHovered ? 6 : 4,
5463
+ fill: series.color || defaultColors[seriesIndex % defaultColors.length],
5464
+ stroke: "white",
5465
+ strokeWidth: "2",
5466
+ className: "cursor-pointer transition-all",
5467
+ onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
5468
+ onMouseLeave: () => setHoveredPoint(null)
5469
+ },
5470
+ `point-${seriesIndex}-${pointIndex}`
5471
+ );
5472
+ })
5473
+ ),
5474
+ xAxisLabel && showXAxis && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5475
+ "text",
5476
+ {
5477
+ x: chartWidth / 2,
5478
+ y: chartHeight + 50,
5479
+ textAnchor: "middle",
5480
+ fontSize: "16",
5481
+ fontWeight: "500",
5482
+ className: "fill-gray-700 dark:fill-gray-300",
5483
+ children: xAxisLabel
5484
+ }
5485
+ ),
5486
+ yAxisLabel && showYAxis && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5487
+ "text",
5488
+ {
5489
+ x: -chartHeight / 2,
5490
+ y: -45,
5491
+ textAnchor: "middle",
5492
+ fontSize: "16",
5493
+ fontWeight: "500",
5494
+ transform: `rotate(-90, 0, 0)`,
5495
+ className: "fill-gray-700 dark:fill-gray-300",
5496
+ children: yAxisLabel
5497
+ }
5498
+ )
5499
+ ] })
5500
+ }
5501
+ ),
5502
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { className: "flex items-center gap-2", children: [
5503
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5504
+ "div",
5328
5505
  {
5329
- x: chartWidth / 2,
5330
- y: chartHeight + 50,
5331
- textAnchor: "middle",
5332
- className: "text-sm font-medium fill-gray-700 dark:fill-gray-300",
5333
- children: xAxisLabel
5506
+ className: "w-4 h-4 rounded-sm",
5507
+ style: {
5508
+ backgroundColor: series.color || defaultColors[index % defaultColors.length]
5509
+ }
5334
5510
  }
5335
5511
  ),
5336
- yAxisLabel && showYAxis && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5337
- "text",
5338
- {
5339
- x: -chartHeight / 2,
5340
- y: -45,
5341
- textAnchor: "middle",
5342
- transform: `rotate(-90, 0, 0)`,
5343
- className: "text-sm font-medium fill-gray-700 dark:fill-gray-300",
5344
- children: yAxisLabel
5345
- }
5346
- )
5347
- ] })
5348
- }
5349
- ),
5350
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { className: "flex items-center gap-2", children: [
5351
- /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
5352
- "div",
5353
- {
5354
- className: "w-4 h-4 rounded-sm",
5355
- style: {
5356
- backgroundColor: series.color || defaultColors[index % defaultColors.length]
5512
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5513
+ ] }, `legend-${index}`)) }),
5514
+ showTooltip && hoveredPoint && /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)(
5515
+ "div",
5516
+ {
5517
+ className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50",
5518
+ style: {
5519
+ left: `${padding.left + hoveredPoint.x + 10}px`,
5520
+ top: `${padding.top + hoveredPoint.y - 30}px`
5521
+ },
5522
+ children: [
5523
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
5524
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { children: [
5525
+ "x: ",
5526
+ data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
5527
+ ] }),
5528
+ /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { children: [
5529
+ "y: ",
5530
+ data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
5531
+ ] })
5532
+ ]
5357
5533
  }
5358
- }
5359
- ),
5360
- /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5361
- ] }, `legend-${index}`)) }),
5362
- showTooltip && hoveredPoint && /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)(
5363
- "div",
5364
- {
5365
- 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",
5366
- style: {
5367
- left: `${padding.left + hoveredPoint.x + 10}px`,
5368
- top: `${padding.top + hoveredPoint.y - 30}px`
5369
- },
5370
- children: [
5371
- /* @__PURE__ */ (0, import_jsx_runtime108.jsx)("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
5372
- /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { children: [
5373
- "x: ",
5374
- data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
5375
- ] }),
5376
- /* @__PURE__ */ (0, import_jsx_runtime108.jsxs)("div", { children: [
5377
- "y: ",
5378
- data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
5379
- ] })
5380
- ]
5381
- }
5382
- )
5383
- ] });
5534
+ )
5535
+ ]
5536
+ }
5537
+ );
5384
5538
  };
5385
5539
 
5386
5540
  // src/components/BarChart.tsx
@@ -5402,8 +5556,10 @@ var defaultColors2 = [
5402
5556
  ];
5403
5557
  var BarChart = ({
5404
5558
  data,
5405
- width = 600,
5406
- height = 400,
5559
+ width: providedWidth,
5560
+ height: providedHeight,
5561
+ aspectRatio = 16 / 9,
5562
+ responsive = true,
5407
5563
  showGrid = true,
5408
5564
  showXAxis = true,
5409
5565
  showYAxis = true,
@@ -5417,6 +5573,8 @@ var BarChart = ({
5417
5573
  xAxisLabel,
5418
5574
  yAxisLabel
5419
5575
  }) => {
5576
+ const height = providedHeight ?? 400;
5577
+ const width = providedWidth ?? (responsive ? 800 : 600);
5420
5578
  const [hoveredBar, setHoveredBar] = import_react27.default.useState(null);
5421
5579
  const padding = {
5422
5580
  top: 20,
@@ -5470,7 +5628,8 @@ var BarChart = ({
5470
5628
  x: -10,
5471
5629
  y: y + 4,
5472
5630
  textAnchor: "end",
5473
- className: "text-xs fill-gray-600 dark:fill-gray-400",
5631
+ fontSize: "14",
5632
+ className: "fill-gray-600 dark:fill-gray-400",
5474
5633
  children: yValue.toFixed(0)
5475
5634
  }
5476
5635
  )
@@ -5566,7 +5725,9 @@ var BarChart = ({
5566
5725
  x: xPos + actualBarWidth / 2,
5567
5726
  y: yPos - 5,
5568
5727
  textAnchor: "middle",
5569
- className: "text-xs fill-gray-700 dark:fill-gray-300 font-medium",
5728
+ fontSize: "14",
5729
+ fontWeight: "500",
5730
+ className: "fill-gray-700 dark:fill-gray-300",
5570
5731
  children: point.y
5571
5732
  },
5572
5733
  `value-${seriesIndex}-${barIndex}`
@@ -5586,79 +5747,93 @@ var BarChart = ({
5586
5747
  x: xPos,
5587
5748
  y: chartHeight + 20,
5588
5749
  textAnchor: "middle",
5589
- className: "text-xs fill-gray-600 dark:fill-gray-400",
5750
+ fontSize: "14",
5751
+ className: "fill-gray-600 dark:fill-gray-400",
5590
5752
  children: point.x
5591
5753
  },
5592
5754
  `x-label-${i}`
5593
5755
  );
5594
5756
  });
5595
- return /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: `relative inline-block ${className}`, children: [
5596
- /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5597
- "svg",
5598
- {
5599
- width,
5600
- height,
5601
- className: "bg-white dark:bg-gray-800",
5602
- style: { overflow: "visible" },
5603
- children: /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5604
- gridLines,
5605
- renderBars(),
5606
- showXAxis && xAxisLabels,
5607
- xAxisLabel && showXAxis && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5608
- "text",
5757
+ return /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
5758
+ "div",
5759
+ {
5760
+ className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
5761
+ style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
5762
+ children: [
5763
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5764
+ "svg",
5765
+ {
5766
+ width: "100%",
5767
+ height: "100%",
5768
+ viewBox: `0 0 ${width} ${height}`,
5769
+ preserveAspectRatio: "xMidYMid meet",
5770
+ className: "bg-white dark:bg-gray-800 block",
5771
+ style: { overflow: "visible" },
5772
+ children: /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5773
+ gridLines,
5774
+ renderBars(),
5775
+ showXAxis && xAxisLabels,
5776
+ xAxisLabel && showXAxis && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5777
+ "text",
5778
+ {
5779
+ x: chartWidth / 2,
5780
+ y: chartHeight + 50,
5781
+ textAnchor: "middle",
5782
+ fontSize: "16",
5783
+ fontWeight: "500",
5784
+ className: "fill-gray-700 dark:fill-gray-300",
5785
+ children: xAxisLabel
5786
+ }
5787
+ ),
5788
+ yAxisLabel && showYAxis && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5789
+ "text",
5790
+ {
5791
+ x: -chartHeight / 2,
5792
+ y: -45,
5793
+ textAnchor: "middle",
5794
+ fontSize: "16",
5795
+ fontWeight: "500",
5796
+ transform: `rotate(-90, 0, 0)`,
5797
+ className: "fill-gray-700 dark:fill-gray-300",
5798
+ children: yAxisLabel
5799
+ }
5800
+ )
5801
+ ] })
5802
+ }
5803
+ ),
5804
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "flex items-center gap-2", children: [
5805
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5806
+ "div",
5609
5807
  {
5610
- x: chartWidth / 2,
5611
- y: chartHeight + 50,
5612
- textAnchor: "middle",
5613
- className: "text-sm font-medium fill-gray-700 dark:fill-gray-300",
5614
- children: xAxisLabel
5808
+ className: "w-4 h-4 rounded-sm",
5809
+ style: {
5810
+ backgroundColor: series.color || defaultColors2[index % defaultColors2.length]
5811
+ }
5615
5812
  }
5616
5813
  ),
5617
- yAxisLabel && showYAxis && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5618
- "text",
5619
- {
5620
- x: -chartHeight / 2,
5621
- y: -45,
5622
- textAnchor: "middle",
5623
- transform: `rotate(-90, 0, 0)`,
5624
- className: "text-sm font-medium fill-gray-700 dark:fill-gray-300",
5625
- children: yAxisLabel
5626
- }
5627
- )
5628
- ] })
5629
- }
5630
- ),
5631
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "flex items-center gap-2", children: [
5632
- /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
5633
- "div",
5634
- {
5635
- className: "w-4 h-4 rounded-sm",
5636
- style: {
5637
- backgroundColor: series.color || defaultColors2[index % defaultColors2.length]
5814
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5815
+ ] }, `legend-${index}`)) }),
5816
+ showTooltip && hoveredBar && /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
5817
+ "div",
5818
+ {
5819
+ className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50",
5820
+ style: {
5821
+ left: `${padding.left + hoveredBar.x + 10}px`,
5822
+ top: `${padding.top + hoveredBar.y - 30}px`
5823
+ },
5824
+ children: [
5825
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "font-semibold", children: data[hoveredBar.seriesIndex].name }),
5826
+ /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { children: [
5827
+ data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].x,
5828
+ ": ",
5829
+ data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].y
5830
+ ] })
5831
+ ]
5638
5832
  }
5639
- }
5640
- ),
5641
- /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5642
- ] }, `legend-${index}`)) }),
5643
- showTooltip && hoveredBar && /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
5644
- "div",
5645
- {
5646
- 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",
5647
- style: {
5648
- left: `${padding.left + hoveredBar.x + 10}px`,
5649
- top: `${padding.top + hoveredBar.y - 30}px`
5650
- },
5651
- children: [
5652
- /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "font-semibold", children: data[hoveredBar.seriesIndex].name }),
5653
- /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { children: [
5654
- data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].x,
5655
- ": ",
5656
- data[hoveredBar.seriesIndex].data[hoveredBar.barIndex].y
5657
- ] })
5658
- ]
5659
- }
5660
- )
5661
- ] });
5833
+ )
5834
+ ]
5835
+ }
5836
+ );
5662
5837
  };
5663
5838
 
5664
5839
  // src/components/AreaChart.tsx
@@ -5680,8 +5855,10 @@ var defaultColors3 = [
5680
5855
  ];
5681
5856
  var AreaChart = ({
5682
5857
  data,
5683
- width = 600,
5684
- height = 400,
5858
+ width: providedWidth,
5859
+ height: providedHeight,
5860
+ aspectRatio = 16 / 9,
5861
+ responsive = true,
5685
5862
  showGrid = true,
5686
5863
  showXAxis = true,
5687
5864
  showYAxis = true,
@@ -5696,6 +5873,8 @@ var AreaChart = ({
5696
5873
  xAxisLabel,
5697
5874
  yAxisLabel
5698
5875
  }) => {
5876
+ const height = providedHeight ?? 400;
5877
+ const width = providedWidth ?? 800;
5699
5878
  const [hoveredPoint, setHoveredPoint] = import_react28.default.useState(null);
5700
5879
  const padding = { top: 20, right: 20, bottom: showXAxis ? 60 : 20, left: showYAxis ? 60 : 20 };
5701
5880
  const chartWidth = width - padding.left - padding.right;
@@ -5805,7 +5984,8 @@ var AreaChart = ({
5805
5984
  x: -10,
5806
5985
  y: y + 4,
5807
5986
  textAnchor: "end",
5808
- className: "text-xs fill-gray-600 dark:fill-gray-400",
5987
+ fontSize: "12",
5988
+ className: "fill-gray-600 dark:fill-gray-400",
5809
5989
  children: yValue.toFixed(0)
5810
5990
  }
5811
5991
  )
@@ -5837,7 +6017,8 @@ var AreaChart = ({
5837
6017
  x,
5838
6018
  y: chartHeight + 20,
5839
6019
  textAnchor: "middle",
5840
- className: "text-xs fill-gray-600 dark:fill-gray-400",
6020
+ fontSize: "12",
6021
+ className: "fill-gray-600 dark:fill-gray-400",
5841
6022
  children: xValue
5842
6023
  }
5843
6024
  )
@@ -5849,130 +6030,142 @@ var AreaChart = ({
5849
6030
  if (stacked) {
5850
6031
  cumulativeValues = Array(data[0]?.data.length || 0).fill(0);
5851
6032
  }
5852
- return /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { className: `relative inline-block ${className}`, children: [
5853
- /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5854
- "svg",
5855
- {
5856
- width,
5857
- height,
5858
- className: "bg-white dark:bg-gray-800",
5859
- style: { overflow: "visible" },
5860
- children: /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
5861
- gridLines,
5862
- data.map((series, seriesIndex) => {
5863
- const baselineYValues = stacked ? [...cumulativeValues] : void 0;
5864
- const areaPath = generateAreaPath(series, baselineYValues);
5865
- const linePath = generateLinePath(series, baselineYValues);
5866
- if (stacked) {
5867
- series.data.forEach((point, i) => {
5868
- cumulativeValues[i] += point.y;
5869
- });
5870
- }
5871
- return /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("g", { children: [
5872
- /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5873
- "path",
6033
+ return /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)(
6034
+ "div",
6035
+ {
6036
+ className: `relative ${responsive ? "w-full" : "inline-block"} ${className}`,
6037
+ style: responsive ? { width: "100%", aspectRatio: `${width} / ${height}` } : void 0,
6038
+ children: [
6039
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6040
+ "svg",
6041
+ {
6042
+ width: "100%",
6043
+ height: "100%",
6044
+ viewBox: `0 0 ${width} ${height}`,
6045
+ preserveAspectRatio: "xMidYMid meet",
6046
+ className: "bg-white dark:bg-gray-800 block",
6047
+ children: /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("g", { transform: `translate(${padding.left}, ${padding.top})`, children: [
6048
+ gridLines,
6049
+ data.map((series, seriesIndex) => {
6050
+ const baselineYValues = stacked ? [...cumulativeValues] : void 0;
6051
+ const areaPath = generateAreaPath(series, baselineYValues);
6052
+ const linePath = generateLinePath(series, baselineYValues);
6053
+ if (stacked) {
6054
+ series.data.forEach((point, i) => {
6055
+ cumulativeValues[i] += point.y;
6056
+ });
6057
+ }
6058
+ return /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("g", { children: [
6059
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6060
+ "path",
6061
+ {
6062
+ d: areaPath,
6063
+ fill: series.color || defaultColors3[seriesIndex % defaultColors3.length],
6064
+ opacity: fillOpacity
6065
+ }
6066
+ ),
6067
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6068
+ "path",
6069
+ {
6070
+ d: linePath,
6071
+ fill: "none",
6072
+ stroke: series.color || defaultColors3[seriesIndex % defaultColors3.length],
6073
+ strokeWidth,
6074
+ strokeLinecap: "round",
6075
+ strokeLinejoin: "round"
6076
+ }
6077
+ )
6078
+ ] }, `area-${seriesIndex}`);
6079
+ }),
6080
+ showDots && data.map((series, seriesIndex) => {
6081
+ const baselineYValues = stacked ? data.slice(0, seriesIndex).reduce((acc, s) => {
6082
+ return acc.map((val, i) => val + (s.data[i]?.y || 0));
6083
+ }, Array(series.data.length).fill(0)) : void 0;
6084
+ return series.data.map((point, pointIndex) => {
6085
+ const x = scaleX(point.x, pointIndex);
6086
+ const y = baselineYValues ? scaleY(baselineYValues[pointIndex] + point.y) : scaleY(point.y);
6087
+ const isHovered = hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex;
6088
+ return /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6089
+ "circle",
6090
+ {
6091
+ cx: x,
6092
+ cy: y,
6093
+ r: isHovered ? 6 : 4,
6094
+ fill: series.color || defaultColors3[seriesIndex % defaultColors3.length],
6095
+ stroke: "white",
6096
+ strokeWidth: "2",
6097
+ className: "cursor-pointer transition-all",
6098
+ onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
6099
+ onMouseLeave: () => setHoveredPoint(null)
6100
+ },
6101
+ `point-${seriesIndex}-${pointIndex}`
6102
+ );
6103
+ });
6104
+ }),
6105
+ xAxisLabel && showXAxis && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6106
+ "text",
5874
6107
  {
5875
- d: areaPath,
5876
- fill: series.color || defaultColors3[seriesIndex % defaultColors3.length],
5877
- opacity: fillOpacity
6108
+ x: chartWidth / 2,
6109
+ y: chartHeight + 50,
6110
+ textAnchor: "middle",
6111
+ fontSize: "14",
6112
+ fontWeight: "500",
6113
+ className: "fill-gray-700 dark:fill-gray-300",
6114
+ children: xAxisLabel
5878
6115
  }
5879
6116
  ),
5880
- /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5881
- "path",
6117
+ yAxisLabel && showYAxis && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6118
+ "text",
5882
6119
  {
5883
- d: linePath,
5884
- fill: "none",
5885
- stroke: series.color || defaultColors3[seriesIndex % defaultColors3.length],
5886
- strokeWidth,
5887
- strokeLinecap: "round",
5888
- strokeLinejoin: "round"
6120
+ x: -chartHeight / 2,
6121
+ y: -45,
6122
+ textAnchor: "middle",
6123
+ fontSize: "14",
6124
+ fontWeight: "500",
6125
+ transform: "rotate(-90, 0, 0)",
6126
+ className: "fill-gray-700 dark:fill-gray-300",
6127
+ children: yAxisLabel
5889
6128
  }
5890
6129
  )
5891
- ] }, `area-${seriesIndex}`);
5892
- }),
5893
- showDots && data.map((series, seriesIndex) => {
5894
- const baselineYValues = stacked ? data.slice(0, seriesIndex).reduce((acc, s) => {
5895
- return acc.map((val, i) => val + (s.data[i]?.y || 0));
5896
- }, Array(series.data.length).fill(0)) : void 0;
5897
- return series.data.map((point, pointIndex) => {
5898
- const x = scaleX(point.x, pointIndex);
5899
- const y = baselineYValues ? scaleY(baselineYValues[pointIndex] + point.y) : scaleY(point.y);
5900
- const isHovered = hoveredPoint?.seriesIndex === seriesIndex && hoveredPoint?.pointIndex === pointIndex;
5901
- return /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5902
- "circle",
5903
- {
5904
- cx: x,
5905
- cy: y,
5906
- r: isHovered ? 6 : 4,
5907
- fill: series.color || defaultColors3[seriesIndex % defaultColors3.length],
5908
- stroke: "white",
5909
- strokeWidth: "2",
5910
- className: "cursor-pointer transition-all",
5911
- onMouseEnter: () => showTooltip && setHoveredPoint({ seriesIndex, pointIndex, x, y }),
5912
- onMouseLeave: () => setHoveredPoint(null)
5913
- },
5914
- `point-${seriesIndex}-${pointIndex}`
5915
- );
5916
- });
5917
- }),
5918
- xAxisLabel && showXAxis && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5919
- "text",
6130
+ ] })
6131
+ }
6132
+ ),
6133
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { className: "flex items-center gap-2", children: [
6134
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
6135
+ "div",
5920
6136
  {
5921
- x: chartWidth / 2,
5922
- y: chartHeight + 50,
5923
- textAnchor: "middle",
5924
- className: "text-sm font-medium fill-gray-700 dark:fill-gray-300",
5925
- children: xAxisLabel
6137
+ className: "w-4 h-4 rounded-sm",
6138
+ style: {
6139
+ backgroundColor: series.color || defaultColors3[index % defaultColors3.length]
6140
+ }
5926
6141
  }
5927
6142
  ),
5928
- yAxisLabel && showYAxis && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5929
- "text",
5930
- {
5931
- x: -chartHeight / 2,
5932
- y: -45,
5933
- textAnchor: "middle",
5934
- transform: `rotate(-90, 0, 0)`,
5935
- className: "text-sm font-medium fill-gray-700 dark:fill-gray-300",
5936
- children: yAxisLabel
5937
- }
5938
- )
5939
- ] })
5940
- }
5941
- ),
5942
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { className: "flex items-center gap-2", children: [
5943
- /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
5944
- "div",
5945
- {
5946
- className: "w-4 h-4 rounded-sm",
5947
- style: {
5948
- backgroundColor: series.color || defaultColors3[index % defaultColors3.length]
6143
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
6144
+ ] }, `legend-${index}`)) }),
6145
+ showTooltip && hoveredPoint && /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)(
6146
+ "div",
6147
+ {
6148
+ className: "absolute bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50",
6149
+ style: {
6150
+ left: `${padding.left + hoveredPoint.x + 10}px`,
6151
+ top: `${padding.top + hoveredPoint.y - 30}px`
6152
+ },
6153
+ children: [
6154
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
6155
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { children: [
6156
+ "x: ",
6157
+ data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
6158
+ ] }),
6159
+ /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { children: [
6160
+ "y: ",
6161
+ data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
6162
+ ] })
6163
+ ]
5949
6164
  }
5950
- }
5951
- ),
5952
- /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: series.name })
5953
- ] }, `legend-${index}`)) }),
5954
- showTooltip && hoveredPoint && /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)(
5955
- "div",
5956
- {
5957
- 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",
5958
- style: {
5959
- left: `${padding.left + hoveredPoint.x + 10}px`,
5960
- top: `${padding.top + hoveredPoint.y - 30}px`
5961
- },
5962
- children: [
5963
- /* @__PURE__ */ (0, import_jsx_runtime110.jsx)("div", { className: "font-semibold", children: data[hoveredPoint.seriesIndex].name }),
5964
- /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { children: [
5965
- "x: ",
5966
- data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].x
5967
- ] }),
5968
- /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)("div", { children: [
5969
- "y: ",
5970
- data[hoveredPoint.seriesIndex].data[hoveredPoint.pointIndex].y
5971
- ] })
5972
- ]
5973
- }
5974
- )
5975
- ] });
6165
+ )
6166
+ ]
6167
+ }
6168
+ );
5976
6169
  };
5977
6170
 
5978
6171
  // src/components/PieChart.tsx
@@ -5998,8 +6191,10 @@ var defaultColors4 = [
5998
6191
  ];
5999
6192
  var PieChart = ({
6000
6193
  data,
6001
- width = 400,
6002
- height = 400,
6194
+ width: providedWidth,
6195
+ height: providedHeight,
6196
+ aspectRatio = 1,
6197
+ responsive = true,
6003
6198
  showLegend = true,
6004
6199
  showLabels = true,
6005
6200
  showValues = false,
@@ -6008,6 +6203,8 @@ var PieChart = ({
6008
6203
  donutWidth = 60,
6009
6204
  className = ""
6010
6205
  }) => {
6206
+ const height = providedHeight ?? 400;
6207
+ const width = providedWidth ?? 400;
6011
6208
  const [hoveredSlice, setHoveredSlice] = import_react29.default.useState(null);
6012
6209
  const total = data.reduce((sum, item) => sum + item.value, 0);
6013
6210
  const centerX = width / 2;
@@ -6065,112 +6262,126 @@ var PieChart = ({
6065
6262
  index
6066
6263
  };
6067
6264
  });
6068
- return /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { className: `relative inline-block ${className}`, children: [
6069
- /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6070
- "svg",
6071
- {
6072
- width,
6073
- height,
6074
- className: "bg-white dark:bg-gray-800",
6075
- children: [
6076
- slices.map((slice) => {
6077
- const isHovered = hoveredSlice === slice.index;
6078
- return /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("g", { children: [
6265
+ return /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6266
+ "div",
6267
+ {
6268
+ className: `relative ${responsive ? "w-full flex justify-center" : "inline-block"} ${className}`,
6269
+ style: responsive ? { aspectRatio: `${width} / ${height}` } : void 0,
6270
+ children: [
6271
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6272
+ "svg",
6273
+ {
6274
+ width: "100%",
6275
+ height: "100%",
6276
+ viewBox: `0 0 ${width} ${height}`,
6277
+ preserveAspectRatio: "xMidYMid meet",
6278
+ className: "bg-white dark:bg-gray-800 block",
6279
+ children: [
6280
+ slices.map((slice) => {
6281
+ const isHovered = hoveredSlice === slice.index;
6282
+ return /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("g", { children: [
6283
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6284
+ "path",
6285
+ {
6286
+ d: slice.path,
6287
+ fill: slice.color,
6288
+ stroke: "white",
6289
+ strokeWidth: "2",
6290
+ className: "cursor-pointer transition-opacity",
6291
+ opacity: isHovered ? 0.8 : 1,
6292
+ onMouseEnter: () => setHoveredSlice(slice.index),
6293
+ onMouseLeave: () => setHoveredSlice(null)
6294
+ }
6295
+ ),
6296
+ showLabels && slice.percentage > 5 && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6297
+ "text",
6298
+ {
6299
+ x: slice.labelX,
6300
+ y: slice.labelY,
6301
+ textAnchor: "middle",
6302
+ dominantBaseline: "middle",
6303
+ fontSize: "14",
6304
+ fontWeight: "600",
6305
+ className: "fill-gray-700 dark:fill-gray-200 pointer-events-none",
6306
+ children: [
6307
+ showPercentages && `${slice.percentage.toFixed(1)}%`,
6308
+ showPercentages && showValues && " ",
6309
+ showValues && `(${slice.value})`,
6310
+ !showPercentages && !showValues && slice.label
6311
+ ]
6312
+ }
6313
+ )
6314
+ ] }, slice.index);
6315
+ }),
6316
+ donut && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("g", { children: [
6317
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6318
+ "text",
6319
+ {
6320
+ x: centerX,
6321
+ y: centerY - 10,
6322
+ textAnchor: "middle",
6323
+ fontSize: "32",
6324
+ fontWeight: "700",
6325
+ className: "fill-gray-900 dark:fill-gray-100",
6326
+ children: total
6327
+ }
6328
+ ),
6329
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6330
+ "text",
6331
+ {
6332
+ x: centerX,
6333
+ y: centerY + 15,
6334
+ textAnchor: "middle",
6335
+ fontSize: "16",
6336
+ className: "fill-gray-600 dark:fill-gray-400",
6337
+ children: "Total"
6338
+ }
6339
+ )
6340
+ ] })
6341
+ ]
6342
+ }
6343
+ ),
6344
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6345
+ "div",
6346
+ {
6347
+ className: "flex items-center gap-2 cursor-pointer",
6348
+ onMouseEnter: () => setHoveredSlice(index),
6349
+ onMouseLeave: () => setHoveredSlice(null),
6350
+ children: [
6079
6351
  /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6080
- "path",
6352
+ "div",
6081
6353
  {
6082
- d: slice.path,
6083
- fill: slice.color,
6084
- stroke: "white",
6085
- strokeWidth: "2",
6086
- className: "cursor-pointer transition-opacity",
6087
- opacity: isHovered ? 0.8 : 1,
6088
- onMouseEnter: () => setHoveredSlice(slice.index),
6089
- onMouseLeave: () => setHoveredSlice(null)
6354
+ className: "w-4 h-4 rounded-sm",
6355
+ style: {
6356
+ backgroundColor: item.color || defaultColors4[index % defaultColors4.length]
6357
+ }
6090
6358
  }
6091
6359
  ),
6092
- showLabels && slice.percentage > 5 && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6093
- "text",
6094
- {
6095
- x: slice.labelX,
6096
- y: slice.labelY,
6097
- textAnchor: "middle",
6098
- dominantBaseline: "middle",
6099
- className: "text-xs font-semibold fill-gray-700 dark:fill-gray-200 pointer-events-none",
6100
- children: [
6101
- showPercentages && `${slice.percentage.toFixed(1)}%`,
6102
- showPercentages && showValues && " ",
6103
- showValues && `(${slice.value})`,
6104
- !showPercentages && !showValues && slice.label
6105
- ]
6106
- }
6107
- )
6108
- ] }, slice.index);
6109
- }),
6110
- donut && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("g", { children: [
6111
- /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6112
- "text",
6113
- {
6114
- x: centerX,
6115
- y: centerY - 10,
6116
- textAnchor: "middle",
6117
- className: "text-2xl font-bold fill-gray-900 dark:fill-gray-100",
6118
- children: total
6119
- }
6120
- ),
6121
- /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6122
- "text",
6123
- {
6124
- x: centerX,
6125
- y: centerY + 15,
6126
- textAnchor: "middle",
6127
- className: "text-sm fill-gray-600 dark:fill-gray-400",
6128
- children: "Total"
6129
- }
6130
- )
6131
- ] })
6132
- ]
6133
- }
6134
- ),
6135
- showLegend && /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "flex flex-wrap gap-4 mt-4 justify-center", children: data.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
6136
- "div",
6137
- {
6138
- className: "flex items-center gap-2 cursor-pointer",
6139
- onMouseEnter: () => setHoveredSlice(index),
6140
- onMouseLeave: () => setHoveredSlice(null),
6141
- children: [
6142
- /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
6143
- "div",
6144
- {
6145
- className: "w-4 h-4 rounded-sm",
6146
- style: {
6147
- backgroundColor: item.color || defaultColors4[index % defaultColors4.length]
6148
- }
6149
- }
6150
- ),
6151
- /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: [
6152
- item.label,
6153
- ": ",
6154
- item.value,
6155
- showPercentages && ` (${(item.value / total * 100).toFixed(1)}%)`
6360
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: [
6361
+ item.label,
6362
+ ": ",
6363
+ item.value,
6364
+ showPercentages && ` (${(item.value / total * 100).toFixed(1)}%)`
6365
+ ] })
6366
+ ]
6367
+ },
6368
+ `legend-${index}`
6369
+ )) }),
6370
+ hoveredSlice !== null && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { className: "absolute top-2 right-2 bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50", children: [
6371
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "font-semibold", children: data[hoveredSlice].label }),
6372
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { children: [
6373
+ "Value: ",
6374
+ data[hoveredSlice].value
6375
+ ] }),
6376
+ /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { children: [
6377
+ "Percentage: ",
6378
+ (data[hoveredSlice].value / total * 100).toFixed(1),
6379
+ "%"
6156
6380
  ] })
6157
- ]
6158
- },
6159
- `legend-${index}`
6160
- )) }),
6161
- hoveredSlice !== null && /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { className: "absolute top-2 right-2 bg-gray-900 dark:bg-gray-700 text-white px-3 py-2 rounded shadow-lg text-sm pointer-events-none z-50", children: [
6162
- /* @__PURE__ */ (0, import_jsx_runtime111.jsx)("div", { className: "font-semibold", children: data[hoveredSlice].label }),
6163
- /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { children: [
6164
- "Value: ",
6165
- data[hoveredSlice].value
6166
- ] }),
6167
- /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)("div", { children: [
6168
- "Percentage: ",
6169
- (data[hoveredSlice].value / total * 100).toFixed(1),
6170
- "%"
6171
- ] })
6172
- ] })
6173
- ] });
6381
+ ] })
6382
+ ]
6383
+ }
6384
+ );
6174
6385
  };
6175
6386
 
6176
6387
  // src/utils/theme-script.ts