@mlw-packages/react-components 1.5.7 → 1.5.8
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 +200 -54
- package/dist/index.d.ts +200 -54
- package/dist/index.js +2545 -445
- package/dist/index.mjs +2581 -434
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4393,11 +4393,87 @@ function ModeToggleBase({
|
|
|
4393
4393
|
] });
|
|
4394
4394
|
}
|
|
4395
4395
|
|
|
4396
|
+
// src/components/ui/DestructiveDialog.tsx
|
|
4397
|
+
import * as React29 from "react";
|
|
4398
|
+
import { XCircleIcon as XCircleIcon2 } from "@phosphor-icons/react";
|
|
4399
|
+
import { jsx as jsx43, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
4400
|
+
var DestructiveDialog = ({
|
|
4401
|
+
title,
|
|
4402
|
+
description,
|
|
4403
|
+
onConfirm,
|
|
4404
|
+
onCancel,
|
|
4405
|
+
children,
|
|
4406
|
+
triggerContent
|
|
4407
|
+
}) => {
|
|
4408
|
+
const titleId = "destructive-dialog-title";
|
|
4409
|
+
const descriptionId = "destructive-dialog-description";
|
|
4410
|
+
const triggerEl = React29.isValidElement(children) ? /* @__PURE__ */ jsx43(AlertDialogTriggerBase, { asChild: true, children }) : /* @__PURE__ */ jsx43(AlertDialogTriggerBase, { children: /* @__PURE__ */ jsx43(ButtonBase, { variant: "destructive", children: triggerContent ?? "Excluir" }) });
|
|
4411
|
+
return /* @__PURE__ */ jsxs25(AlertDialogBase, { children: [
|
|
4412
|
+
triggerEl,
|
|
4413
|
+
/* @__PURE__ */ jsxs25(
|
|
4414
|
+
AlertDialogContentBase,
|
|
4415
|
+
{
|
|
4416
|
+
role: "alertdialog",
|
|
4417
|
+
"aria-modal": "true",
|
|
4418
|
+
"aria-labelledby": titleId,
|
|
4419
|
+
"aria-describedby": descriptionId,
|
|
4420
|
+
className: cn("border border-destructive bg-background"),
|
|
4421
|
+
children: [
|
|
4422
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-start gap-4", children: [
|
|
4423
|
+
/* @__PURE__ */ jsx43("div", { className: "flex items-center justify-center w-10 h-10 rounded-full ring-1 ring-destructive/30", children: /* @__PURE__ */ jsx43(XCircleIcon2, { className: "w-6 h-6 text-destructive" }) }),
|
|
4424
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex-1", children: [
|
|
4425
|
+
/* @__PURE__ */ jsx43(
|
|
4426
|
+
AlertDialogTitleBase,
|
|
4427
|
+
{
|
|
4428
|
+
id: titleId,
|
|
4429
|
+
className: "text-lg sm:text-xl font-semibold text-destructive",
|
|
4430
|
+
children: title
|
|
4431
|
+
}
|
|
4432
|
+
),
|
|
4433
|
+
/* @__PURE__ */ jsx43(
|
|
4434
|
+
AlertDialogDescriptionBase,
|
|
4435
|
+
{
|
|
4436
|
+
id: descriptionId,
|
|
4437
|
+
className: "mt-2 text-sm text-muted-foreground",
|
|
4438
|
+
children: description
|
|
4439
|
+
}
|
|
4440
|
+
)
|
|
4441
|
+
] })
|
|
4442
|
+
] }),
|
|
4443
|
+
/* @__PURE__ */ jsxs25(AlertDialogFooterBase, { className: "mt-2 flex justify-end gap-3", children: [
|
|
4444
|
+
/* @__PURE__ */ jsx43(
|
|
4445
|
+
AlertDialogCancelBase,
|
|
4446
|
+
{
|
|
4447
|
+
onClick: onCancel,
|
|
4448
|
+
className: cn(
|
|
4449
|
+
buttonVariantsBase({ variant: "outline", size: "default" }),
|
|
4450
|
+
"hover:bg-foreground/5 hover:text-primary hover:opacity-90 hover:shadow-none"
|
|
4451
|
+
),
|
|
4452
|
+
children: "Cancelar"
|
|
4453
|
+
}
|
|
4454
|
+
),
|
|
4455
|
+
/* @__PURE__ */ jsx43(
|
|
4456
|
+
AlertDialogActionBase,
|
|
4457
|
+
{
|
|
4458
|
+
onClick: onConfirm,
|
|
4459
|
+
className: cn(
|
|
4460
|
+
buttonVariantsBase({ variant: "destructive", size: "default" })
|
|
4461
|
+
),
|
|
4462
|
+
children: "Confirmar"
|
|
4463
|
+
}
|
|
4464
|
+
)
|
|
4465
|
+
] })
|
|
4466
|
+
]
|
|
4467
|
+
}
|
|
4468
|
+
)
|
|
4469
|
+
] });
|
|
4470
|
+
};
|
|
4471
|
+
|
|
4396
4472
|
// src/components/date-time-picker/DateTimePicker.tsx
|
|
4397
4473
|
import { add, format } from "date-fns";
|
|
4398
4474
|
|
|
4399
4475
|
// src/components/date-time-picker/calendar.tsx
|
|
4400
|
-
import * as
|
|
4476
|
+
import * as React30 from "react";
|
|
4401
4477
|
import { DayPicker as DayPicker2 } from "react-day-picker";
|
|
4402
4478
|
import {
|
|
4403
4479
|
CaretLeftIcon as CaretLeftIcon2,
|
|
@@ -4406,35 +4482,35 @@ import {
|
|
|
4406
4482
|
CalendarIcon
|
|
4407
4483
|
} from "@phosphor-icons/react";
|
|
4408
4484
|
import { AnimatePresence as AnimatePresence4 } from "framer-motion";
|
|
4409
|
-
import { jsx as
|
|
4485
|
+
import { jsx as jsx44, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4410
4486
|
function CalendarBase2({
|
|
4411
4487
|
className,
|
|
4412
4488
|
classNames,
|
|
4413
4489
|
showOutsideDays = true,
|
|
4414
4490
|
...props
|
|
4415
4491
|
}) {
|
|
4416
|
-
const [month, setMonth] =
|
|
4492
|
+
const [month, setMonth] = React30.useState(
|
|
4417
4493
|
props.month || props.defaultMonth || /* @__PURE__ */ new Date()
|
|
4418
4494
|
);
|
|
4419
|
-
const [direction, setDirection] =
|
|
4495
|
+
const [direction, setDirection] = React30.useState(1);
|
|
4420
4496
|
const handleMonthChange = (newMonth) => {
|
|
4421
4497
|
const isNext = newMonth > month ? 1 : -1;
|
|
4422
4498
|
setDirection(isNext);
|
|
4423
4499
|
setMonth(newMonth);
|
|
4424
4500
|
props.onMonthChange?.(newMonth);
|
|
4425
4501
|
};
|
|
4426
|
-
return /* @__PURE__ */
|
|
4502
|
+
return /* @__PURE__ */ jsx44(
|
|
4427
4503
|
"div",
|
|
4428
4504
|
{
|
|
4429
4505
|
className: cn(
|
|
4430
4506
|
"rounded-2xl border bg-background p-4 shadow-lg overflow-hidden w-full h-full flex flex-col",
|
|
4431
4507
|
className
|
|
4432
4508
|
),
|
|
4433
|
-
children: /* @__PURE__ */
|
|
4509
|
+
children: /* @__PURE__ */ jsx44("div", { className: "relative flex-1 flex flex-col min-h-0", children: /* @__PURE__ */ jsx44(AnimatePresence4, { initial: false, mode: "wait", custom: direction, children: /* @__PURE__ */ jsx44(
|
|
4434
4510
|
"div",
|
|
4435
4511
|
{
|
|
4436
4512
|
className: "w-full h-full flex flex-col",
|
|
4437
|
-
children: /* @__PURE__ */
|
|
4513
|
+
children: /* @__PURE__ */ jsx44(
|
|
4438
4514
|
DayPicker2,
|
|
4439
4515
|
{
|
|
4440
4516
|
showOutsideDays,
|
|
@@ -4483,8 +4559,8 @@ function CalendarBase2({
|
|
|
4483
4559
|
...classNames
|
|
4484
4560
|
},
|
|
4485
4561
|
components: {
|
|
4486
|
-
IconLeft: () => /* @__PURE__ */
|
|
4487
|
-
IconRight: () => /* @__PURE__ */
|
|
4562
|
+
IconLeft: () => /* @__PURE__ */ jsx44(CaretLeftIcon2, { className: "h-4 w-4" }),
|
|
4563
|
+
IconRight: () => /* @__PURE__ */ jsx44(CaretRightIcon5, { className: "h-4 w-4" })
|
|
4488
4564
|
},
|
|
4489
4565
|
...props
|
|
4490
4566
|
}
|
|
@@ -4503,11 +4579,11 @@ import { useEffect as useEffect7, useState as useState8 } from "react";
|
|
|
4503
4579
|
|
|
4504
4580
|
// src/components/date-time-picker/TimePicker.tsx
|
|
4505
4581
|
import { motion as motion6, AnimatePresence as AnimatePresence5 } from "framer-motion";
|
|
4506
|
-
import * as
|
|
4582
|
+
import * as React32 from "react";
|
|
4507
4583
|
|
|
4508
4584
|
// src/components/date-time-picker/TimePickerInput.tsx
|
|
4509
4585
|
import { CaretUpIcon as CaretUpIcon2, CaretDownIcon as CaretDownIcon4 } from "@phosphor-icons/react";
|
|
4510
|
-
import
|
|
4586
|
+
import React31 from "react";
|
|
4511
4587
|
|
|
4512
4588
|
// src/components/date-time-picker/time-picker-utils.ts
|
|
4513
4589
|
function isValidHour(value) {
|
|
@@ -4649,8 +4725,8 @@ function display12HourValue(hours) {
|
|
|
4649
4725
|
}
|
|
4650
4726
|
|
|
4651
4727
|
// src/components/date-time-picker/TimePickerInput.tsx
|
|
4652
|
-
import { jsx as
|
|
4653
|
-
var TimePickerInput =
|
|
4728
|
+
import { jsx as jsx45, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4729
|
+
var TimePickerInput = React31.forwardRef(
|
|
4654
4730
|
({
|
|
4655
4731
|
className,
|
|
4656
4732
|
type = "tel",
|
|
@@ -4669,10 +4745,10 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4669
4745
|
label,
|
|
4670
4746
|
...props
|
|
4671
4747
|
}, ref) => {
|
|
4672
|
-
const [flag, setFlag] =
|
|
4673
|
-
const [prevIntKey, setPrevIntKey] =
|
|
4674
|
-
const [isFocused, setIsFocused] =
|
|
4675
|
-
|
|
4748
|
+
const [flag, setFlag] = React31.useState(false);
|
|
4749
|
+
const [prevIntKey, setPrevIntKey] = React31.useState("0");
|
|
4750
|
+
const [isFocused, setIsFocused] = React31.useState(false);
|
|
4751
|
+
React31.useEffect(() => {
|
|
4676
4752
|
if (flag) {
|
|
4677
4753
|
const timer = setTimeout(() => {
|
|
4678
4754
|
setFlag(false);
|
|
@@ -4680,7 +4756,7 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4680
4756
|
return () => clearTimeout(timer);
|
|
4681
4757
|
}
|
|
4682
4758
|
}, [flag]);
|
|
4683
|
-
const calculatedValue =
|
|
4759
|
+
const calculatedValue = React31.useMemo(() => {
|
|
4684
4760
|
return getDateByType(date, picker);
|
|
4685
4761
|
}, [date, picker]);
|
|
4686
4762
|
const calculateNewValue = (key) => {
|
|
@@ -4736,8 +4812,8 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4736
4812
|
const baseLabel = getPickerLabel();
|
|
4737
4813
|
return `${baseLabel}, valor atual: ${calculatedValue}.`;
|
|
4738
4814
|
};
|
|
4739
|
-
return /* @__PURE__ */
|
|
4740
|
-
getPickerLabel() && /* @__PURE__ */
|
|
4815
|
+
return /* @__PURE__ */ jsxs27("div", { className: "relative group flex flex-col items-center", children: [
|
|
4816
|
+
getPickerLabel() && /* @__PURE__ */ jsx45(
|
|
4741
4817
|
"label",
|
|
4742
4818
|
{
|
|
4743
4819
|
htmlFor: id || picker,
|
|
@@ -4745,7 +4821,7 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4745
4821
|
children: getPickerLabel()
|
|
4746
4822
|
}
|
|
4747
4823
|
),
|
|
4748
|
-
/* @__PURE__ */
|
|
4824
|
+
/* @__PURE__ */ jsxs27(
|
|
4749
4825
|
"div",
|
|
4750
4826
|
{
|
|
4751
4827
|
className: cn(
|
|
@@ -4753,7 +4829,7 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4753
4829
|
"transition-all duration-200"
|
|
4754
4830
|
),
|
|
4755
4831
|
children: [
|
|
4756
|
-
showArrows && /* @__PURE__ */
|
|
4832
|
+
showArrows && /* @__PURE__ */ jsx45(
|
|
4757
4833
|
"button",
|
|
4758
4834
|
{
|
|
4759
4835
|
type: "button",
|
|
@@ -4769,11 +4845,11 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4769
4845
|
),
|
|
4770
4846
|
tabIndex: -1,
|
|
4771
4847
|
"aria-label": `Incrementar ${getPickerLabel().toLowerCase()}`,
|
|
4772
|
-
children: /* @__PURE__ */
|
|
4848
|
+
children: /* @__PURE__ */ jsx45(CaretUpIcon2, { size: 14, className: "sm:w-4 sm:h-4" })
|
|
4773
4849
|
}
|
|
4774
4850
|
),
|
|
4775
|
-
/* @__PURE__ */
|
|
4776
|
-
/* @__PURE__ */
|
|
4851
|
+
/* @__PURE__ */ jsxs27("div", { className: "relative", children: [
|
|
4852
|
+
/* @__PURE__ */ jsx45(
|
|
4777
4853
|
"input",
|
|
4778
4854
|
{
|
|
4779
4855
|
ref,
|
|
@@ -4818,9 +4894,9 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4818
4894
|
...props
|
|
4819
4895
|
}
|
|
4820
4896
|
),
|
|
4821
|
-
isFocused && /* @__PURE__ */
|
|
4897
|
+
isFocused && /* @__PURE__ */ jsx45("div", { className: "absolute inset-0 rounded-lg ring-2 ring-primary/20 pointer-events-none animate-pulse" })
|
|
4822
4898
|
] }),
|
|
4823
|
-
showArrows && /* @__PURE__ */
|
|
4899
|
+
showArrows && /* @__PURE__ */ jsx45(
|
|
4824
4900
|
"button",
|
|
4825
4901
|
{
|
|
4826
4902
|
type: "button",
|
|
@@ -4836,7 +4912,7 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4836
4912
|
),
|
|
4837
4913
|
tabIndex: -1,
|
|
4838
4914
|
"aria-label": `Decrementar ${getPickerLabel().toLowerCase()}`,
|
|
4839
|
-
children: /* @__PURE__ */
|
|
4915
|
+
children: /* @__PURE__ */ jsx45(CaretDownIcon4, { size: 14, className: "sm:w-4 sm:h-4" })
|
|
4840
4916
|
}
|
|
4841
4917
|
)
|
|
4842
4918
|
]
|
|
@@ -4848,16 +4924,16 @@ var TimePickerInput = React30.forwardRef(
|
|
|
4848
4924
|
TimePickerInput.displayName = "TimePickerInput";
|
|
4849
4925
|
|
|
4850
4926
|
// src/components/date-time-picker/TimePicker.tsx
|
|
4851
|
-
import { Fragment as Fragment4, jsx as
|
|
4927
|
+
import { Fragment as Fragment4, jsx as jsx46, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4852
4928
|
function TimePicker({
|
|
4853
4929
|
date,
|
|
4854
4930
|
setDate,
|
|
4855
4931
|
hideSeconds,
|
|
4856
4932
|
enableButton
|
|
4857
4933
|
}) {
|
|
4858
|
-
const minuteRef =
|
|
4859
|
-
const hourRef =
|
|
4860
|
-
const secondRef =
|
|
4934
|
+
const minuteRef = React32.useRef(null);
|
|
4935
|
+
const hourRef = React32.useRef(null);
|
|
4936
|
+
const secondRef = React32.useRef(null);
|
|
4861
4937
|
const containerVariants = {
|
|
4862
4938
|
hidden: { opacity: 0, y: 10 },
|
|
4863
4939
|
visible: {
|
|
@@ -4873,7 +4949,7 @@ function TimePicker({
|
|
|
4873
4949
|
hidden: { opacity: 0, y: 10 },
|
|
4874
4950
|
visible: { opacity: 1, y: 0 }
|
|
4875
4951
|
};
|
|
4876
|
-
return /* @__PURE__ */
|
|
4952
|
+
return /* @__PURE__ */ jsxs28(
|
|
4877
4953
|
motion6.div,
|
|
4878
4954
|
{
|
|
4879
4955
|
variants: containerVariants,
|
|
@@ -4881,12 +4957,12 @@ function TimePicker({
|
|
|
4881
4957
|
animate: "visible",
|
|
4882
4958
|
className: "flex items-end justify-center gap-2 sm:gap-3 p-2 sm:p-3 md:p-4 rounded-lg bg-muted/20 border border-border/50 w-full max-w-full overflow-hidden",
|
|
4883
4959
|
children: [
|
|
4884
|
-
/* @__PURE__ */
|
|
4960
|
+
/* @__PURE__ */ jsx46(
|
|
4885
4961
|
motion6.div,
|
|
4886
4962
|
{
|
|
4887
4963
|
variants: itemVariants2,
|
|
4888
4964
|
className: "grid gap-1 sm:gap-2 text-center flex-shrink-0 min-w-0",
|
|
4889
|
-
children: /* @__PURE__ */
|
|
4965
|
+
children: /* @__PURE__ */ jsx46(
|
|
4890
4966
|
TimePickerInput,
|
|
4891
4967
|
{
|
|
4892
4968
|
picker: "hours",
|
|
@@ -4899,12 +4975,12 @@ function TimePicker({
|
|
|
4899
4975
|
)
|
|
4900
4976
|
}
|
|
4901
4977
|
),
|
|
4902
|
-
/* @__PURE__ */
|
|
4978
|
+
/* @__PURE__ */ jsx46(
|
|
4903
4979
|
motion6.div,
|
|
4904
4980
|
{
|
|
4905
4981
|
variants: itemVariants2,
|
|
4906
4982
|
className: "grid gap-1 sm:gap-2 text-center flex-shrink-0 min-w-0",
|
|
4907
|
-
children: /* @__PURE__ */
|
|
4983
|
+
children: /* @__PURE__ */ jsx46(
|
|
4908
4984
|
TimePickerInput,
|
|
4909
4985
|
{
|
|
4910
4986
|
picker: "minutes",
|
|
@@ -4918,7 +4994,7 @@ function TimePicker({
|
|
|
4918
4994
|
)
|
|
4919
4995
|
}
|
|
4920
4996
|
),
|
|
4921
|
-
/* @__PURE__ */
|
|
4997
|
+
/* @__PURE__ */ jsx46(AnimatePresence5, { children: !hideSeconds && /* @__PURE__ */ jsx46(Fragment4, { children: /* @__PURE__ */ jsx46(
|
|
4922
4998
|
motion6.div,
|
|
4923
4999
|
{
|
|
4924
5000
|
variants: itemVariants2,
|
|
@@ -4926,7 +5002,7 @@ function TimePicker({
|
|
|
4926
5002
|
animate: "visible",
|
|
4927
5003
|
exit: "hidden",
|
|
4928
5004
|
className: "grid gap-1 sm:gap-2 text-center flex-shrink-0 min-w-0",
|
|
4929
|
-
children: /* @__PURE__ */
|
|
5005
|
+
children: /* @__PURE__ */ jsx46(
|
|
4930
5006
|
TimePickerInput,
|
|
4931
5007
|
{
|
|
4932
5008
|
picker: "seconds",
|
|
@@ -4946,7 +5022,7 @@ function TimePicker({
|
|
|
4946
5022
|
|
|
4947
5023
|
// src/components/date-time-picker/DateTimePicker.tsx
|
|
4948
5024
|
import { CalendarBlankIcon, ClockIcon } from "@phosphor-icons/react";
|
|
4949
|
-
import { jsx as
|
|
5025
|
+
import { jsx as jsx47, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
4950
5026
|
function DateTimePicker({
|
|
4951
5027
|
label,
|
|
4952
5028
|
date,
|
|
@@ -4995,10 +5071,10 @@ function DateTimePicker({
|
|
|
4995
5071
|
setInternalDate(date);
|
|
4996
5072
|
}
|
|
4997
5073
|
}, [date, open]);
|
|
4998
|
-
return /* @__PURE__ */
|
|
4999
|
-
label && /* @__PURE__ */
|
|
5000
|
-
/* @__PURE__ */
|
|
5001
|
-
/* @__PURE__ */
|
|
5074
|
+
return /* @__PURE__ */ jsxs29("div", { className: cn("space-y-2 w-full sm:w-auto", className), children: [
|
|
5075
|
+
label && /* @__PURE__ */ jsx47(LabelBase_default, { children: label }),
|
|
5076
|
+
/* @__PURE__ */ jsxs29(PopoverBase, { open, onOpenChange: setOpen, children: [
|
|
5077
|
+
/* @__PURE__ */ jsx47(PopoverTriggerBase, { disabled, asChild: true, children: /* @__PURE__ */ jsxs29(
|
|
5002
5078
|
ButtonBase,
|
|
5003
5079
|
{
|
|
5004
5080
|
variant: "outline",
|
|
@@ -5010,12 +5086,12 @@ function DateTimePicker({
|
|
|
5010
5086
|
!date && "text-muted-foreground"
|
|
5011
5087
|
),
|
|
5012
5088
|
children: [
|
|
5013
|
-
/* @__PURE__ */
|
|
5014
|
-
/* @__PURE__ */
|
|
5089
|
+
/* @__PURE__ */ jsx47("span", { className: "truncate flex-1", children: date ? format(date, getDisplayFormat(), { locale: ptBR }) : "Pick a date" }),
|
|
5090
|
+
/* @__PURE__ */ jsx47(CalendarBlankIcon, { className: "flex-shrink-0 w-5 h-5 sm:w-6 sm:h-6" })
|
|
5015
5091
|
]
|
|
5016
5092
|
}
|
|
5017
5093
|
) }),
|
|
5018
|
-
/* @__PURE__ */
|
|
5094
|
+
/* @__PURE__ */ jsx47(
|
|
5019
5095
|
PopoverContentBase,
|
|
5020
5096
|
{
|
|
5021
5097
|
className: "w-full p-0",
|
|
@@ -5024,8 +5100,8 @@ function DateTimePicker({
|
|
|
5024
5100
|
side: "bottom",
|
|
5025
5101
|
avoidCollisions: true,
|
|
5026
5102
|
collisionPadding: 8,
|
|
5027
|
-
children: /* @__PURE__ */
|
|
5028
|
-
/* @__PURE__ */
|
|
5103
|
+
children: /* @__PURE__ */ jsxs29("div", { className: "flex flex-col space-y-2 sm:space-y-3 p-2 sm:p-3 md:p-4 max-h-[calc(100vh-4rem)] overflow-y-auto", children: [
|
|
5104
|
+
/* @__PURE__ */ jsx47(
|
|
5029
5105
|
CalendarBase2,
|
|
5030
5106
|
{
|
|
5031
5107
|
mode: "single",
|
|
@@ -5038,13 +5114,13 @@ function DateTimePicker({
|
|
|
5038
5114
|
className: "w-full"
|
|
5039
5115
|
}
|
|
5040
5116
|
),
|
|
5041
|
-
!(hideHour && hideMinute) && /* @__PURE__ */
|
|
5117
|
+
!(hideHour && hideMinute) && /* @__PURE__ */ jsx47("div", { className: "flex justify-center w-full px-2", children: /* @__PURE__ */ jsxs29(
|
|
5042
5118
|
PopoverBase,
|
|
5043
5119
|
{
|
|
5044
5120
|
open: timePickerOpen,
|
|
5045
5121
|
onOpenChange: setTimePickerOpen,
|
|
5046
5122
|
children: [
|
|
5047
|
-
/* @__PURE__ */
|
|
5123
|
+
/* @__PURE__ */ jsx47(PopoverTriggerBase, { asChild: true, children: /* @__PURE__ */ jsxs29(
|
|
5048
5124
|
ButtonBase,
|
|
5049
5125
|
{
|
|
5050
5126
|
variant: "outline",
|
|
@@ -5060,14 +5136,14 @@ function DateTimePicker({
|
|
|
5060
5136
|
"min-h-[36px] sm:min-h-[40px]"
|
|
5061
5137
|
),
|
|
5062
5138
|
children: [
|
|
5063
|
-
/* @__PURE__ */
|
|
5064
|
-
/* @__PURE__ */
|
|
5139
|
+
/* @__PURE__ */ jsx47(ClockIcon, { className: "text-primary/70 flex-shrink-0 w-4 h-4 sm:w-5 sm:h-5" }),
|
|
5140
|
+
/* @__PURE__ */ jsx47("span", { className: "text-foreground truncate", children: internalDate ? format(internalDate, getTimeFormat() || "HH:mm", {
|
|
5065
5141
|
locale: ptBR
|
|
5066
5142
|
}) : "00:00" })
|
|
5067
5143
|
]
|
|
5068
5144
|
}
|
|
5069
5145
|
) }),
|
|
5070
|
-
/* @__PURE__ */
|
|
5146
|
+
/* @__PURE__ */ jsx47(
|
|
5071
5147
|
PopoverContentBase,
|
|
5072
5148
|
{
|
|
5073
5149
|
className: "w-[calc(100vw-2rem)] max-w-sm p-3 sm:p-3 rounded-md",
|
|
@@ -5076,9 +5152,9 @@ function DateTimePicker({
|
|
|
5076
5152
|
sideOffset: 8,
|
|
5077
5153
|
avoidCollisions: true,
|
|
5078
5154
|
collisionPadding: 8,
|
|
5079
|
-
children: /* @__PURE__ */
|
|
5080
|
-
/* @__PURE__ */
|
|
5081
|
-
/* @__PURE__ */
|
|
5155
|
+
children: /* @__PURE__ */ jsxs29("div", { className: "flex flex-col items-center space-y-2 sm:space-y-3", children: [
|
|
5156
|
+
/* @__PURE__ */ jsx47("h4", { className: "text-sm sm:text-base font-medium text-center", children: "Alterar Hor\xE1rio" }),
|
|
5157
|
+
/* @__PURE__ */ jsx47(
|
|
5082
5158
|
TimePicker,
|
|
5083
5159
|
{
|
|
5084
5160
|
setDate: handleTimeChange,
|
|
@@ -5086,7 +5162,7 @@ function DateTimePicker({
|
|
|
5086
5162
|
hideSeconds
|
|
5087
5163
|
}
|
|
5088
5164
|
),
|
|
5089
|
-
/* @__PURE__ */
|
|
5165
|
+
/* @__PURE__ */ jsx47(
|
|
5090
5166
|
ButtonBase,
|
|
5091
5167
|
{
|
|
5092
5168
|
size: "sm",
|
|
@@ -5110,7 +5186,7 @@ function DateTimePicker({
|
|
|
5110
5186
|
}
|
|
5111
5187
|
|
|
5112
5188
|
// src/components/selects/Select.tsx
|
|
5113
|
-
import { Fragment as Fragment5, jsx as
|
|
5189
|
+
import { Fragment as Fragment5, jsx as jsx48, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
5114
5190
|
function Select({
|
|
5115
5191
|
items,
|
|
5116
5192
|
groupItems,
|
|
@@ -5119,9 +5195,9 @@ function Select({
|
|
|
5119
5195
|
errorMessage,
|
|
5120
5196
|
testIds = {}
|
|
5121
5197
|
}) {
|
|
5122
|
-
return /* @__PURE__ */
|
|
5123
|
-
/* @__PURE__ */
|
|
5124
|
-
/* @__PURE__ */
|
|
5198
|
+
return /* @__PURE__ */ jsxs30("div", { "data-testid": testIds.root ?? "select-root", children: [
|
|
5199
|
+
/* @__PURE__ */ jsxs30(SelectBase, { onValueChange: onChange, "data-testid": testIds.base ?? "select-base", children: [
|
|
5200
|
+
/* @__PURE__ */ jsx48(
|
|
5125
5201
|
SelectTriggerBase,
|
|
5126
5202
|
{
|
|
5127
5203
|
className: cn(
|
|
@@ -5129,7 +5205,7 @@ function Select({
|
|
|
5129
5205
|
errorMessage && "border-red-500"
|
|
5130
5206
|
),
|
|
5131
5207
|
"data-testid": testIds.trigger ?? "select-trigger",
|
|
5132
|
-
children: /* @__PURE__ */
|
|
5208
|
+
children: /* @__PURE__ */ jsx48(
|
|
5133
5209
|
SelectValueBase,
|
|
5134
5210
|
{
|
|
5135
5211
|
placeholder,
|
|
@@ -5138,9 +5214,9 @@ function Select({
|
|
|
5138
5214
|
)
|
|
5139
5215
|
}
|
|
5140
5216
|
),
|
|
5141
|
-
/* @__PURE__ */
|
|
5142
|
-
/* @__PURE__ */
|
|
5143
|
-
groupItems[key].map((item) => /* @__PURE__ */
|
|
5217
|
+
/* @__PURE__ */ jsx48(ScrollAreaBase, { "data-testid": testIds.scrollarea ?? "select-scrollarea", children: /* @__PURE__ */ jsx48(SelectContentBase, { "data-testid": testIds.content ?? "select-content", children: groupItems ? /* @__PURE__ */ jsx48(Fragment5, { children: Object.keys(groupItems).map((key) => /* @__PURE__ */ jsxs30(SelectGroupBase, { "data-testid": testIds.group ?? "select-group", children: [
|
|
5218
|
+
/* @__PURE__ */ jsx48(SelectLabelBase, { "data-testid": testIds.label ?? "select-label", children: key }),
|
|
5219
|
+
groupItems[key].map((item) => /* @__PURE__ */ jsx48(
|
|
5144
5220
|
SelectItemBase,
|
|
5145
5221
|
{
|
|
5146
5222
|
value: item.value,
|
|
@@ -5149,7 +5225,7 @@ function Select({
|
|
|
5149
5225
|
},
|
|
5150
5226
|
item.value
|
|
5151
5227
|
))
|
|
5152
|
-
] }, key)) }) : /* @__PURE__ */
|
|
5228
|
+
] }, key)) }) : /* @__PURE__ */ jsx48(SelectGroupBase, { "data-testid": testIds.group ?? "select-group", children: items.map((item) => /* @__PURE__ */ jsx48(
|
|
5153
5229
|
SelectItemBase,
|
|
5154
5230
|
{
|
|
5155
5231
|
value: item.value,
|
|
@@ -5159,7 +5235,7 @@ function Select({
|
|
|
5159
5235
|
item.value
|
|
5160
5236
|
)) }) }) })
|
|
5161
5237
|
] }),
|
|
5162
|
-
errorMessage && /* @__PURE__ */
|
|
5238
|
+
errorMessage && /* @__PURE__ */ jsx48(
|
|
5163
5239
|
"p",
|
|
5164
5240
|
{
|
|
5165
5241
|
className: "text-sm text-red-500",
|
|
@@ -5170,141 +5246,233 @@ function Select({
|
|
|
5170
5246
|
] });
|
|
5171
5247
|
}
|
|
5172
5248
|
|
|
5173
|
-
// src/components/
|
|
5174
|
-
import
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
className: cn("border border-destructive bg-background"),
|
|
5198
|
-
children: [
|
|
5199
|
-
/* @__PURE__ */ jsxs30("div", { className: "flex items-start gap-4", children: [
|
|
5200
|
-
/* @__PURE__ */ jsx48("div", { className: "flex items-center justify-center w-10 h-10 rounded-full ring-1 ring-destructive/30", children: /* @__PURE__ */ jsx48(XCircleIcon2, { className: "w-6 h-6 text-destructive" }) }),
|
|
5201
|
-
/* @__PURE__ */ jsxs30("div", { className: "flex-1", children: [
|
|
5202
|
-
/* @__PURE__ */ jsx48(
|
|
5203
|
-
AlertDialogTitleBase,
|
|
5204
|
-
{
|
|
5205
|
-
id: titleId,
|
|
5206
|
-
className: "text-lg sm:text-xl font-semibold text-destructive",
|
|
5207
|
-
children: title
|
|
5208
|
-
}
|
|
5209
|
-
),
|
|
5210
|
-
/* @__PURE__ */ jsx48(
|
|
5211
|
-
AlertDialogDescriptionBase,
|
|
5212
|
-
{
|
|
5213
|
-
id: descriptionId,
|
|
5214
|
-
className: "mt-2 text-sm text-muted-foreground",
|
|
5215
|
-
children: description
|
|
5216
|
-
}
|
|
5217
|
-
)
|
|
5218
|
-
] })
|
|
5219
|
-
] }),
|
|
5220
|
-
/* @__PURE__ */ jsxs30(AlertDialogFooterBase, { className: "mt-2 flex justify-end gap-3", children: [
|
|
5221
|
-
/* @__PURE__ */ jsx48(
|
|
5222
|
-
AlertDialogCancelBase,
|
|
5223
|
-
{
|
|
5224
|
-
onClick: onCancel,
|
|
5225
|
-
className: cn(
|
|
5226
|
-
buttonVariantsBase({ variant: "outline", size: "default" }),
|
|
5227
|
-
"hover:bg-foreground/5 hover:text-primary hover:opacity-90 hover:shadow-none"
|
|
5228
|
-
),
|
|
5229
|
-
children: "Cancelar"
|
|
5230
|
-
}
|
|
5231
|
-
),
|
|
5232
|
-
/* @__PURE__ */ jsx48(
|
|
5233
|
-
AlertDialogActionBase,
|
|
5234
|
-
{
|
|
5235
|
-
onClick: onConfirm,
|
|
5236
|
-
className: cn(
|
|
5237
|
-
buttonVariantsBase({ variant: "destructive", size: "default" })
|
|
5238
|
-
),
|
|
5239
|
-
children: "Confirmar"
|
|
5240
|
-
}
|
|
5241
|
-
)
|
|
5242
|
-
] })
|
|
5243
|
-
]
|
|
5244
|
-
}
|
|
5245
|
-
)
|
|
5246
|
-
] });
|
|
5247
|
-
};
|
|
5249
|
+
// src/components/charts/Chart.tsx
|
|
5250
|
+
import {
|
|
5251
|
+
useState as useState11,
|
|
5252
|
+
useEffect as useEffect10,
|
|
5253
|
+
useCallback as useCallback7,
|
|
5254
|
+
useMemo as useMemo6,
|
|
5255
|
+
useRef as useRef4,
|
|
5256
|
+
useLayoutEffect
|
|
5257
|
+
} from "react";
|
|
5258
|
+
import {
|
|
5259
|
+
ComposedChart,
|
|
5260
|
+
Bar,
|
|
5261
|
+
Line,
|
|
5262
|
+
Area,
|
|
5263
|
+
Rectangle,
|
|
5264
|
+
ReferenceLine,
|
|
5265
|
+
XAxis,
|
|
5266
|
+
YAxis,
|
|
5267
|
+
CartesianGrid,
|
|
5268
|
+
Tooltip,
|
|
5269
|
+
Legend,
|
|
5270
|
+
LabelList,
|
|
5271
|
+
ResponsiveContainer
|
|
5272
|
+
} from "recharts";
|
|
5248
5273
|
|
|
5249
|
-
// src/components/charts/
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
import { DotsThreeIcon as DotsThreeIcon2 } from "@phosphor-icons/react/dist/ssr";
|
|
5253
|
-
import { Check } from "@phosphor-icons/react/dist/ssr";
|
|
5254
|
-
import { jsx as jsx49, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5255
|
-
var menuVariants = {
|
|
5256
|
-
hidden: { opacity: 0, y: -6, scale: 0.98 },
|
|
5257
|
-
visible: { opacity: 1, y: 0, scale: 1 },
|
|
5258
|
-
exit: { opacity: 0, y: -6, scale: 0.98 }
|
|
5274
|
+
// src/components/charts/utils/helpers.ts
|
|
5275
|
+
var formatFieldName = (fieldName) => {
|
|
5276
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/[_-]/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()).trim();
|
|
5259
5277
|
};
|
|
5260
|
-
var
|
|
5261
|
-
|
|
5262
|
-
|
|
5278
|
+
var detectDataFields = (data, xAxisKey) => {
|
|
5279
|
+
if (!data || data.length === 0) return [];
|
|
5280
|
+
const firstItem = data[0];
|
|
5281
|
+
return Object.keys(firstItem).filter(
|
|
5282
|
+
(key) => key !== xAxisKey && typeof firstItem[key] === "number"
|
|
5283
|
+
);
|
|
5263
5284
|
};
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
}
|
|
5272
|
-
|
|
5273
|
-
const
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5285
|
+
var detectXAxis = (data) => {
|
|
5286
|
+
if (!data || data.length === 0) return "name";
|
|
5287
|
+
const firstItem = data[0];
|
|
5288
|
+
const stringFields = Object.keys(firstItem).filter(
|
|
5289
|
+
(key) => typeof firstItem[key] === "string" || typeof firstItem[key] === "number" && String(firstItem[key]).length <= 4
|
|
5290
|
+
);
|
|
5291
|
+
return stringFields[0] || Object.keys(firstItem)[0] || "name";
|
|
5292
|
+
};
|
|
5293
|
+
var generateAdditionalColors = (baseColors, count) => {
|
|
5294
|
+
const hexToRgb = (hex) => {
|
|
5295
|
+
const clean = hex.replace("#", "");
|
|
5296
|
+
const bigint = parseInt(
|
|
5297
|
+
clean.length === 3 ? clean.split("").map((c) => c + c).join("") : clean,
|
|
5298
|
+
16
|
|
5299
|
+
);
|
|
5300
|
+
return { r: bigint >> 16 & 255, g: bigint >> 8 & 255, b: bigint & 255 };
|
|
5301
|
+
};
|
|
5302
|
+
const rgbToHsl = ({ r, g, b }) => {
|
|
5303
|
+
r /= 255;
|
|
5304
|
+
g /= 255;
|
|
5305
|
+
b /= 255;
|
|
5306
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
5307
|
+
let h = 0;
|
|
5308
|
+
let s = 0;
|
|
5309
|
+
const l = (max + min) / 2;
|
|
5310
|
+
if (max !== min) {
|
|
5311
|
+
const d = max - min;
|
|
5312
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
5313
|
+
switch (max) {
|
|
5314
|
+
case r:
|
|
5315
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
5316
|
+
break;
|
|
5317
|
+
case g:
|
|
5318
|
+
h = (b - r) / d + 2;
|
|
5319
|
+
break;
|
|
5320
|
+
case b:
|
|
5321
|
+
h = (r - g) / d + 4;
|
|
5322
|
+
break;
|
|
5323
|
+
}
|
|
5324
|
+
h /= 6;
|
|
5325
|
+
}
|
|
5326
|
+
return {
|
|
5327
|
+
h: Math.round(h * 360),
|
|
5328
|
+
s: Math.round(s * 100),
|
|
5329
|
+
l: Math.round(l * 100)
|
|
5284
5330
|
};
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5331
|
+
};
|
|
5332
|
+
const hslToHex = (h, s, l) => {
|
|
5333
|
+
s /= 100;
|
|
5334
|
+
l /= 100;
|
|
5335
|
+
const k = (n) => (n + h / 30) % 5;
|
|
5336
|
+
const a = s * Math.min(l, 1 - l);
|
|
5337
|
+
const f = (n) => {
|
|
5338
|
+
const color = l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
5339
|
+
return Math.round(255 * color).toString(16).padStart(2, "0");
|
|
5290
5340
|
};
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5341
|
+
return `#${f(0)}${f(8)}${f(4)}`;
|
|
5342
|
+
};
|
|
5343
|
+
const anchors = baseColors.map((c) => rgbToHsl(hexToRgb(c)));
|
|
5344
|
+
const colors2 = [...baseColors];
|
|
5345
|
+
let i = 0;
|
|
5346
|
+
while (colors2.length < count) {
|
|
5347
|
+
const anchor = anchors[i % anchors.length];
|
|
5348
|
+
const step = Math.floor(i / anchors.length + 1);
|
|
5349
|
+
const hueOffset = step * 25 * (i % 2 === 0 ? 1 : -1);
|
|
5350
|
+
const satOffset = i % 3 === 0 ? -6 : 6;
|
|
5351
|
+
const lightOffset = i % 4 === 0 ? 6 : -4;
|
|
5352
|
+
const newH = (anchor.h + hueOffset + 360) % 360;
|
|
5353
|
+
const newS = Math.max(30, Math.min(95, anchor.s + satOffset));
|
|
5354
|
+
const newL = Math.max(25, Math.min(45, anchor.l + lightOffset));
|
|
5355
|
+
colors2.push(hslToHex(newH, newS, newL));
|
|
5356
|
+
i += 1;
|
|
5357
|
+
}
|
|
5358
|
+
return colors2.slice(0, count);
|
|
5359
|
+
};
|
|
5360
|
+
var niceCeil = (value) => {
|
|
5361
|
+
if (!isFinite(value) || value <= 0) return 1;
|
|
5362
|
+
const pow = Math.pow(10, Math.floor(Math.log10(value)));
|
|
5363
|
+
const normalized = value / pow;
|
|
5364
|
+
const multipliers = [
|
|
5365
|
+
1,
|
|
5366
|
+
1.25,
|
|
5367
|
+
1.5,
|
|
5368
|
+
2,
|
|
5369
|
+
2.5,
|
|
5370
|
+
3,
|
|
5371
|
+
4,
|
|
5372
|
+
5,
|
|
5373
|
+
7.5,
|
|
5374
|
+
10,
|
|
5375
|
+
15,
|
|
5376
|
+
20,
|
|
5377
|
+
25,
|
|
5378
|
+
50,
|
|
5379
|
+
100
|
|
5380
|
+
];
|
|
5381
|
+
for (const m of multipliers) {
|
|
5382
|
+
if (m >= normalized) return Math.ceil(m * pow);
|
|
5383
|
+
}
|
|
5384
|
+
return Math.ceil(100 * pow);
|
|
5385
|
+
};
|
|
5386
|
+
var compactTick = (value) => {
|
|
5387
|
+
if (value >= 1e9)
|
|
5388
|
+
return (value / 1e9).toFixed(1).replace(/\.0$/, "") + "B";
|
|
5389
|
+
if (value >= 1e6)
|
|
5390
|
+
return (value / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
5391
|
+
if (value >= 1e3) return (value / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
5392
|
+
return String(value);
|
|
5393
|
+
};
|
|
5394
|
+
var resolveContainerPaddingLeft = (padding, containerPaddingLeft, defaultLeft = 16) => {
|
|
5395
|
+
if (typeof padding === "number") return padding;
|
|
5396
|
+
if (padding && typeof padding === "object" && padding.left != null)
|
|
5397
|
+
return padding.left;
|
|
5398
|
+
if (typeof containerPaddingLeft === "number") return containerPaddingLeft;
|
|
5399
|
+
return defaultLeft;
|
|
5400
|
+
};
|
|
5401
|
+
var resolveChartMargins = (margins, chartMargins, showLabels) => {
|
|
5402
|
+
const defaultRight = 30;
|
|
5403
|
+
const defaultLeft = 20;
|
|
5404
|
+
const topDefault = showLabels ? 48 : 20;
|
|
5405
|
+
const bottomDefault = 5;
|
|
5406
|
+
return {
|
|
5407
|
+
top: margins?.top ?? chartMargins?.top ?? topDefault,
|
|
5408
|
+
right: margins?.right ?? chartMargins?.right ?? defaultRight,
|
|
5409
|
+
left: margins?.left ?? chartMargins?.left ?? defaultLeft,
|
|
5410
|
+
bottom: margins?.bottom ?? chartMargins?.bottom ?? bottomDefault
|
|
5411
|
+
};
|
|
5412
|
+
};
|
|
5413
|
+
|
|
5414
|
+
// src/components/charts/Chart.tsx
|
|
5415
|
+
import { toast as toast2 } from "sonner";
|
|
5416
|
+
|
|
5417
|
+
// src/components/charts/components/controls/PeriodsDropdown.tsx
|
|
5418
|
+
import { useState as useState9, useRef as useRef2, useEffect as useEffect8 } from "react";
|
|
5419
|
+
import { motion as motion7, AnimatePresence as AnimatePresence6 } from "framer-motion";
|
|
5420
|
+
import { DotsThreeIcon as DotsThreeIcon2 } from "@phosphor-icons/react/dist/ssr";
|
|
5421
|
+
import { Check } from "@phosphor-icons/react/dist/ssr";
|
|
5422
|
+
import { jsx as jsx49, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5423
|
+
var menuVariants = {
|
|
5424
|
+
hidden: { opacity: 0, y: -6, scale: 0.98 },
|
|
5425
|
+
visible: { opacity: 1, y: 0, scale: 1 },
|
|
5426
|
+
exit: { opacity: 0, y: -6, scale: 0.98 }
|
|
5427
|
+
};
|
|
5428
|
+
var itemVariants = {
|
|
5429
|
+
hidden: { opacity: 0, x: -6 },
|
|
5430
|
+
visible: { opacity: 1, x: 0 }
|
|
5431
|
+
};
|
|
5432
|
+
function PeriodsDropdown({
|
|
5433
|
+
processedData,
|
|
5434
|
+
onOpenPeriod,
|
|
5435
|
+
rightOffset,
|
|
5436
|
+
topOffset,
|
|
5437
|
+
activePeriod,
|
|
5438
|
+
activePeriods
|
|
5439
|
+
}) {
|
|
5440
|
+
const periods = processedData.map((d) => String(d.name));
|
|
5441
|
+
const [open, setOpen] = useState9(false);
|
|
5442
|
+
const wrapperRef = useRef2(null);
|
|
5443
|
+
const firstItemRef = useRef2(null);
|
|
5444
|
+
const listRef = useRef2(null);
|
|
5445
|
+
useEffect8(() => {
|
|
5446
|
+
const handleClickOutside = (e) => {
|
|
5447
|
+
if (!wrapperRef.current) return;
|
|
5448
|
+
if (!wrapperRef.current.contains(e.target)) setOpen(false);
|
|
5449
|
+
};
|
|
5450
|
+
const handleEscape = (e) => {
|
|
5451
|
+
if (e.key === "Escape") setOpen(false);
|
|
5452
|
+
};
|
|
5453
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
5454
|
+
document.addEventListener("keydown", handleEscape);
|
|
5455
|
+
return () => {
|
|
5456
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
5457
|
+
document.removeEventListener("keydown", handleEscape);
|
|
5458
|
+
};
|
|
5459
|
+
}, []);
|
|
5460
|
+
useEffect8(() => {
|
|
5461
|
+
if (open && firstItemRef.current) {
|
|
5462
|
+
firstItemRef.current.focus();
|
|
5463
|
+
}
|
|
5464
|
+
}, [open]);
|
|
5465
|
+
function handleSelect(p) {
|
|
5466
|
+
onOpenPeriod(p);
|
|
5467
|
+
setOpen(false);
|
|
5468
|
+
}
|
|
5469
|
+
const containerStyle = typeof rightOffset === "number" ? { position: "relative", zIndex: 30 } : { position: "relative", zIndex: 30 };
|
|
5470
|
+
return /* @__PURE__ */ jsxs31("div", { ref: wrapperRef, style: containerStyle, className: "mr-4", children: [
|
|
5471
|
+
/* @__PURE__ */ jsxs31(
|
|
5472
|
+
"button",
|
|
5473
|
+
{
|
|
5474
|
+
className: "relative p-2.5 rounded-md hover:bg-accent/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-accent/50 transition flex items-center justify-center",
|
|
5475
|
+
"aria-expanded": open,
|
|
5308
5476
|
"aria-haspopup": "menu",
|
|
5309
5477
|
"aria-controls": "periods-menu",
|
|
5310
5478
|
onClick: () => setOpen((v) => !v),
|
|
@@ -6375,200 +6543,60 @@ var TooltipSimple = ({
|
|
|
6375
6543
|
};
|
|
6376
6544
|
var TooltipSimple_default = TooltipSimple;
|
|
6377
6545
|
|
|
6378
|
-
// src/components/charts/utils/
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6546
|
+
// src/components/charts/utils/pillLabelRenderer.tsx
|
|
6547
|
+
import { jsx as jsx56, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
6548
|
+
var formatCompactNumber = (value) => {
|
|
6549
|
+
const isNegative = value < 0;
|
|
6550
|
+
const absValue = Math.abs(value);
|
|
6551
|
+
let formatted;
|
|
6552
|
+
if (absValue >= 1e9) {
|
|
6553
|
+
formatted = (absValue / 1e9).toFixed(1).replace(/\.0$/, "") + "B";
|
|
6554
|
+
} else if (absValue >= 1e6) {
|
|
6555
|
+
formatted = (absValue / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
6556
|
+
} else if (absValue >= 1e3) {
|
|
6557
|
+
formatted = (absValue / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
6558
|
+
} else {
|
|
6559
|
+
formatted = absValue.toString();
|
|
6560
|
+
}
|
|
6561
|
+
return isNegative ? `-${formatted}` : formatted;
|
|
6388
6562
|
};
|
|
6389
|
-
var
|
|
6390
|
-
if (
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
);
|
|
6395
|
-
return stringFields[0] || Object.keys(firstItem)[0] || "name";
|
|
6563
|
+
var parseNumber = (v) => {
|
|
6564
|
+
if (typeof v === "number") return v;
|
|
6565
|
+
if (typeof v === "string" && v.trim() !== "" && !Number.isNaN(Number(v)))
|
|
6566
|
+
return Number(v);
|
|
6567
|
+
return void 0;
|
|
6396
6568
|
};
|
|
6397
|
-
var
|
|
6398
|
-
|
|
6399
|
-
const
|
|
6400
|
-
const
|
|
6401
|
-
|
|
6402
|
-
|
|
6569
|
+
var renderPillLabel = (color, variant) => {
|
|
6570
|
+
return (props) => {
|
|
6571
|
+
const { x, y, value } = props;
|
|
6572
|
+
const text = typeof value === "number" ? formatCompactNumber(value) : String(value ?? "");
|
|
6573
|
+
const paddingX = 8;
|
|
6574
|
+
const approxCharWidth = 7;
|
|
6575
|
+
const pillWidth = Math.max(
|
|
6576
|
+
40,
|
|
6577
|
+
String(text).length * approxCharWidth + paddingX * 2
|
|
6403
6578
|
);
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
h = (r - g) / d + 4;
|
|
6426
|
-
break;
|
|
6427
|
-
}
|
|
6428
|
-
h /= 6;
|
|
6429
|
-
}
|
|
6430
|
-
return {
|
|
6431
|
-
h: Math.round(h * 360),
|
|
6432
|
-
s: Math.round(s * 100),
|
|
6433
|
-
l: Math.round(l * 100)
|
|
6434
|
-
};
|
|
6435
|
-
};
|
|
6436
|
-
const hslToHex = (h, s, l) => {
|
|
6437
|
-
s /= 100;
|
|
6438
|
-
l /= 100;
|
|
6439
|
-
const k = (n) => (n + h / 30) % 5;
|
|
6440
|
-
const a = s * Math.min(l, 1 - l);
|
|
6441
|
-
const f = (n) => {
|
|
6442
|
-
const color = l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
6443
|
-
return Math.round(255 * color).toString(16).padStart(2, "0");
|
|
6444
|
-
};
|
|
6445
|
-
return `#${f(0)}${f(8)}${f(4)}`;
|
|
6446
|
-
};
|
|
6447
|
-
const anchors = baseColors.map((c) => rgbToHsl(hexToRgb(c)));
|
|
6448
|
-
const colors2 = [...baseColors];
|
|
6449
|
-
let i = 0;
|
|
6450
|
-
while (colors2.length < count) {
|
|
6451
|
-
const anchor = anchors[i % anchors.length];
|
|
6452
|
-
const step = Math.floor(i / anchors.length + 1);
|
|
6453
|
-
const hueOffset = step * 25 * (i % 2 === 0 ? 1 : -1);
|
|
6454
|
-
const satOffset = i % 3 === 0 ? -6 : 6;
|
|
6455
|
-
const lightOffset = i % 4 === 0 ? 6 : -4;
|
|
6456
|
-
const newH = (anchor.h + hueOffset + 360) % 360;
|
|
6457
|
-
const newS = Math.max(30, Math.min(95, anchor.s + satOffset));
|
|
6458
|
-
const newL = Math.max(25, Math.min(45, anchor.l + lightOffset));
|
|
6459
|
-
colors2.push(hslToHex(newH, newS, newL));
|
|
6460
|
-
i += 1;
|
|
6461
|
-
}
|
|
6462
|
-
return colors2.slice(0, count);
|
|
6463
|
-
};
|
|
6464
|
-
var niceCeil = (value) => {
|
|
6465
|
-
if (!isFinite(value) || value <= 0) return 1;
|
|
6466
|
-
const pow = Math.pow(10, Math.floor(Math.log10(value)));
|
|
6467
|
-
const normalized = value / pow;
|
|
6468
|
-
const multipliers = [
|
|
6469
|
-
1,
|
|
6470
|
-
1.25,
|
|
6471
|
-
1.5,
|
|
6472
|
-
2,
|
|
6473
|
-
2.5,
|
|
6474
|
-
3,
|
|
6475
|
-
4,
|
|
6476
|
-
5,
|
|
6477
|
-
7.5,
|
|
6478
|
-
10,
|
|
6479
|
-
15,
|
|
6480
|
-
20,
|
|
6481
|
-
25,
|
|
6482
|
-
50,
|
|
6483
|
-
100
|
|
6484
|
-
];
|
|
6485
|
-
for (const m of multipliers) {
|
|
6486
|
-
if (m >= normalized) return Math.ceil(m * pow);
|
|
6487
|
-
}
|
|
6488
|
-
return Math.ceil(100 * pow);
|
|
6489
|
-
};
|
|
6490
|
-
var compactTick = (value) => {
|
|
6491
|
-
if (value >= 1e9)
|
|
6492
|
-
return (value / 1e9).toFixed(1).replace(/\.0$/, "") + "B";
|
|
6493
|
-
if (value >= 1e6)
|
|
6494
|
-
return (value / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
6495
|
-
if (value >= 1e3) return (value / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
6496
|
-
return String(value);
|
|
6497
|
-
};
|
|
6498
|
-
var resolveContainerPaddingLeft = (padding, containerPaddingLeft, defaultLeft = 16) => {
|
|
6499
|
-
if (typeof padding === "number") return padding;
|
|
6500
|
-
if (padding && typeof padding === "object" && padding.left != null)
|
|
6501
|
-
return padding.left;
|
|
6502
|
-
if (typeof containerPaddingLeft === "number") return containerPaddingLeft;
|
|
6503
|
-
return defaultLeft;
|
|
6504
|
-
};
|
|
6505
|
-
var resolveChartMargins = (margins, chartMargins, showLabels) => {
|
|
6506
|
-
const defaultRight = 30;
|
|
6507
|
-
const defaultLeft = 20;
|
|
6508
|
-
const topDefault = showLabels ? 48 : 20;
|
|
6509
|
-
const bottomDefault = 5;
|
|
6510
|
-
return {
|
|
6511
|
-
top: margins?.top ?? chartMargins?.top ?? topDefault,
|
|
6512
|
-
right: margins?.right ?? chartMargins?.right ?? defaultRight,
|
|
6513
|
-
left: margins?.left ?? chartMargins?.left ?? defaultLeft,
|
|
6514
|
-
bottom: margins?.bottom ?? chartMargins?.bottom ?? bottomDefault
|
|
6515
|
-
};
|
|
6516
|
-
};
|
|
6517
|
-
|
|
6518
|
-
// src/components/charts/utils/pillLabelRenderer.tsx
|
|
6519
|
-
import { jsx as jsx56, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
6520
|
-
var formatCompactNumber = (value) => {
|
|
6521
|
-
const isNegative = value < 0;
|
|
6522
|
-
const absValue = Math.abs(value);
|
|
6523
|
-
let formatted;
|
|
6524
|
-
if (absValue >= 1e9) {
|
|
6525
|
-
formatted = (absValue / 1e9).toFixed(1).replace(/\.0$/, "") + "B";
|
|
6526
|
-
} else if (absValue >= 1e6) {
|
|
6527
|
-
formatted = (absValue / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
6528
|
-
} else if (absValue >= 1e3) {
|
|
6529
|
-
formatted = (absValue / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
6530
|
-
} else {
|
|
6531
|
-
formatted = absValue.toString();
|
|
6532
|
-
}
|
|
6533
|
-
return isNegative ? `-${formatted}` : formatted;
|
|
6534
|
-
};
|
|
6535
|
-
var parseNumber = (v) => {
|
|
6536
|
-
if (typeof v === "number") return v;
|
|
6537
|
-
if (typeof v === "string" && v.trim() !== "" && !Number.isNaN(Number(v)))
|
|
6538
|
-
return Number(v);
|
|
6539
|
-
return void 0;
|
|
6540
|
-
};
|
|
6541
|
-
var renderPillLabel = (color, variant) => {
|
|
6542
|
-
return (props) => {
|
|
6543
|
-
const { x, y, value } = props;
|
|
6544
|
-
const text = typeof value === "number" ? formatCompactNumber(value) : String(value ?? "");
|
|
6545
|
-
const paddingX = 8;
|
|
6546
|
-
const approxCharWidth = 7;
|
|
6547
|
-
const pillWidth = Math.max(
|
|
6548
|
-
40,
|
|
6549
|
-
String(text).length * approxCharWidth + paddingX * 2
|
|
6550
|
-
);
|
|
6551
|
-
const pillHeight = 20;
|
|
6552
|
-
const xNum = parseNumber(x);
|
|
6553
|
-
const px = parseNumber(props.x);
|
|
6554
|
-
const pWidth = parseNumber(props.width);
|
|
6555
|
-
const vb = props.viewBox;
|
|
6556
|
-
const cxNum = parseNumber(props.cx);
|
|
6557
|
-
let centerX;
|
|
6558
|
-
if (typeof px === "number" && typeof pWidth === "number") {
|
|
6559
|
-
centerX = px + pWidth / 2;
|
|
6560
|
-
} else if (typeof xNum === "number" && typeof pWidth === "number") {
|
|
6561
|
-
centerX = xNum + pWidth / 2;
|
|
6562
|
-
} else if (typeof cxNum === "number") {
|
|
6563
|
-
centerX = cxNum;
|
|
6564
|
-
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number" && typeof props.index === "number") {
|
|
6565
|
-
const approxCols = Math.max(1, props.index + 1);
|
|
6566
|
-
const colWidth = vb.width / approxCols;
|
|
6567
|
-
centerX = vb.x + colWidth * (props.index + 0.5);
|
|
6568
|
-
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number") {
|
|
6569
|
-
centerX = vb.x + vb.width / 2;
|
|
6570
|
-
} else {
|
|
6571
|
-
centerX = typeof props.index === "number" ? props.index * 40 + 24 : 0;
|
|
6579
|
+
const pillHeight = 20;
|
|
6580
|
+
const xNum = parseNumber(x);
|
|
6581
|
+
const px = parseNumber(props.x);
|
|
6582
|
+
const pWidth = parseNumber(props.width);
|
|
6583
|
+
const vb = props.viewBox;
|
|
6584
|
+
const cxNum = parseNumber(props.cx);
|
|
6585
|
+
let centerX;
|
|
6586
|
+
if (typeof px === "number" && typeof pWidth === "number") {
|
|
6587
|
+
centerX = px + pWidth / 2;
|
|
6588
|
+
} else if (typeof xNum === "number" && typeof pWidth === "number") {
|
|
6589
|
+
centerX = xNum + pWidth / 2;
|
|
6590
|
+
} else if (typeof cxNum === "number") {
|
|
6591
|
+
centerX = cxNum;
|
|
6592
|
+
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number" && typeof props.index === "number") {
|
|
6593
|
+
const approxCols = Math.max(1, props.index + 1);
|
|
6594
|
+
const colWidth = vb.width / approxCols;
|
|
6595
|
+
centerX = vb.x + colWidth * (props.index + 0.5);
|
|
6596
|
+
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number") {
|
|
6597
|
+
centerX = vb.x + vb.width / 2;
|
|
6598
|
+
} else {
|
|
6599
|
+
centerX = typeof props.index === "number" ? props.index * 40 + 24 : 0;
|
|
6572
6600
|
}
|
|
6573
6601
|
if (vb && typeof vb.x === "number" && typeof vb.width === "number") {
|
|
6574
6602
|
const minX = vb.x + 0 + pillWidth / 22;
|
|
@@ -6630,51 +6658,2165 @@ var renderPillLabel = (color, variant) => {
|
|
|
6630
6658
|
};
|
|
6631
6659
|
var pillLabelRenderer_default = renderPillLabel;
|
|
6632
6660
|
|
|
6633
|
-
// src/
|
|
6634
|
-
import {
|
|
6635
|
-
var
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6661
|
+
// src/components/charts/Chart.tsx
|
|
6662
|
+
import { jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
6663
|
+
var DEFAULT_COLORS = ["#55af7d", "#8e68ff", "#2273e1"];
|
|
6664
|
+
var Chart = ({
|
|
6665
|
+
data,
|
|
6666
|
+
series,
|
|
6667
|
+
className,
|
|
6668
|
+
height = 350,
|
|
6669
|
+
width = "100%",
|
|
6670
|
+
colors: colors2 = DEFAULT_COLORS,
|
|
6671
|
+
gridColor,
|
|
6672
|
+
showGrid = true,
|
|
6673
|
+
showTooltip = true,
|
|
6674
|
+
showLegend = true,
|
|
6675
|
+
title,
|
|
6676
|
+
titlePosition = "left",
|
|
6677
|
+
showLabels = false,
|
|
6678
|
+
xAxis,
|
|
6679
|
+
labelMap,
|
|
6680
|
+
enableHighlights = false,
|
|
6681
|
+
enableShowOnly = false,
|
|
6682
|
+
enablePeriodsDropdown = false,
|
|
6683
|
+
enableDraggableTooltips = false,
|
|
6684
|
+
showTooltipTotal = false,
|
|
6685
|
+
maxTooltips = 5,
|
|
6686
|
+
chartMargin
|
|
6687
|
+
}) => {
|
|
6688
|
+
const smartConfig = useMemo6(() => {
|
|
6689
|
+
const resolvedXAxisKey = typeof xAxis === "string" ? xAxis : xAxis && xAxis.dataKey || detectXAxis(data);
|
|
6690
|
+
const xAxisConfig2 = typeof xAxis === "string" ? {
|
|
6691
|
+
dataKey: resolvedXAxisKey,
|
|
6692
|
+
label: formatFieldName(resolvedXAxisKey),
|
|
6693
|
+
autoLabel: true
|
|
6694
|
+
} : {
|
|
6695
|
+
dataKey: resolvedXAxisKey,
|
|
6696
|
+
label: xAxis?.label ?? formatFieldName(resolvedXAxisKey),
|
|
6697
|
+
formatter: xAxis?.formatter,
|
|
6698
|
+
autoLabel: xAxis?.autoLabel ?? true
|
|
6660
6699
|
};
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6700
|
+
const detectedFields = detectDataFields(data, xAxisConfig2.dataKey);
|
|
6701
|
+
const mapperConfig2 = detectedFields.reduce((acc, field) => {
|
|
6702
|
+
acc[field] = {
|
|
6703
|
+
label: labelMap?.[field] ?? formatFieldName(field),
|
|
6704
|
+
type: "number",
|
|
6705
|
+
visible: true
|
|
6706
|
+
};
|
|
6707
|
+
return acc;
|
|
6708
|
+
}, {});
|
|
6709
|
+
return { xAxisConfig: xAxisConfig2, mapperConfig: mapperConfig2 };
|
|
6710
|
+
}, [data, xAxis, labelMap]);
|
|
6711
|
+
const { xAxisConfig, mapperConfig } = smartConfig;
|
|
6712
|
+
const [activeTooltips, setActiveTooltips] = useState11([]);
|
|
6713
|
+
const [highlightedSeries, setHighlightedSeries] = useState11(
|
|
6714
|
+
/* @__PURE__ */ new Set()
|
|
6715
|
+
);
|
|
6716
|
+
const [showOnlyHighlighted, setShowOnlyHighlighted] = useState11(false);
|
|
6717
|
+
useEffect10(() => {
|
|
6718
|
+
if (highlightedSeries.size === 0 && showOnlyHighlighted) {
|
|
6719
|
+
setShowOnlyHighlighted(false);
|
|
6672
6720
|
}
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6721
|
+
}, [highlightedSeries, showOnlyHighlighted]);
|
|
6722
|
+
const processedData = data.map((item) => ({
|
|
6723
|
+
...item,
|
|
6724
|
+
name: String(item[xAxisConfig.dataKey] || "N/A")
|
|
6725
|
+
}));
|
|
6726
|
+
const wrapperRef = useRef4(null);
|
|
6727
|
+
const [measuredWidth, setMeasuredWidth] = useState11(null);
|
|
6728
|
+
useLayoutEffect(() => {
|
|
6729
|
+
const el = wrapperRef.current;
|
|
6730
|
+
if (!el) return;
|
|
6731
|
+
const ro = new ResizeObserver((entries) => {
|
|
6732
|
+
const r = entries[0];
|
|
6733
|
+
if (r && typeof r.contentRect.width === "number") {
|
|
6734
|
+
setMeasuredWidth(Math.round(r.contentRect.width));
|
|
6735
|
+
}
|
|
6736
|
+
});
|
|
6737
|
+
ro.observe(el);
|
|
6738
|
+
setMeasuredWidth(Math.round(el.getBoundingClientRect().width));
|
|
6739
|
+
return () => ro.disconnect();
|
|
6740
|
+
}, []);
|
|
6741
|
+
const seriesOrder = [];
|
|
6742
|
+
if (series) {
|
|
6743
|
+
if (series.bar)
|
|
6744
|
+
series.bar.forEach((k) => seriesOrder.push({ type: "bar", key: k }));
|
|
6745
|
+
if (series.line)
|
|
6746
|
+
series.line.forEach((k) => seriesOrder.push({ type: "line", key: k }));
|
|
6747
|
+
if (series.area)
|
|
6748
|
+
series.area.forEach((k) => seriesOrder.push({ type: "area", key: k }));
|
|
6749
|
+
} else {
|
|
6750
|
+
Object.keys(mapperConfig).forEach(
|
|
6751
|
+
(k) => seriesOrder.push({ type: "bar", key: k })
|
|
6752
|
+
);
|
|
6753
|
+
}
|
|
6754
|
+
const allKeys = seriesOrder.map((s) => s.key).filter(Boolean);
|
|
6755
|
+
const generateColors = useCallback7(
|
|
6756
|
+
(dataKeys) => {
|
|
6757
|
+
const colorMap = {};
|
|
6758
|
+
const allColors = generateAdditionalColors(colors2, dataKeys.length);
|
|
6759
|
+
dataKeys.forEach((key, index) => {
|
|
6760
|
+
colorMap[key] = mapperConfig[key]?.color || allColors[index] || colors2[index % colors2.length];
|
|
6761
|
+
});
|
|
6762
|
+
return colorMap;
|
|
6763
|
+
},
|
|
6764
|
+
[colors2, mapperConfig]
|
|
6765
|
+
);
|
|
6766
|
+
const finalColors = useMemo6(
|
|
6767
|
+
() => generateColors(allKeys),
|
|
6768
|
+
[generateColors, allKeys]
|
|
6769
|
+
);
|
|
6770
|
+
const adaptDataForTooltip = useCallback7(
|
|
6771
|
+
(universalData) => ({
|
|
6772
|
+
...universalData,
|
|
6773
|
+
name: String(universalData[xAxisConfig.dataKey] || "N/A")
|
|
6774
|
+
}),
|
|
6775
|
+
[xAxisConfig.dataKey]
|
|
6776
|
+
);
|
|
6777
|
+
const activePeriods = useMemo6(
|
|
6778
|
+
() => activeTooltips.map((t) => adaptDataForTooltip(t.data).name),
|
|
6779
|
+
[activeTooltips, adaptDataForTooltip]
|
|
6780
|
+
);
|
|
6677
6781
|
useEffect10(() => {
|
|
6782
|
+
window.dispatchEvent(new Event("recountTooltips"));
|
|
6783
|
+
}, [activeTooltips.length]);
|
|
6784
|
+
const toggleHighlight = useCallback7((key) => {
|
|
6785
|
+
setHighlightedSeries((prev) => {
|
|
6786
|
+
const next = new Set(prev);
|
|
6787
|
+
if (next.has(key)) next.delete(key);
|
|
6788
|
+
else next.add(key);
|
|
6789
|
+
return next;
|
|
6790
|
+
});
|
|
6791
|
+
}, []);
|
|
6792
|
+
const maxDataValue = useMemo6(() => {
|
|
6793
|
+
let max = 0;
|
|
6794
|
+
const numericKeys = allKeys;
|
|
6795
|
+
for (const row of processedData) {
|
|
6796
|
+
const r = row;
|
|
6797
|
+
for (const key of numericKeys) {
|
|
6798
|
+
const v = r[key];
|
|
6799
|
+
if (typeof v === "number" && Number.isFinite(v) && v > max) max = v;
|
|
6800
|
+
}
|
|
6801
|
+
}
|
|
6802
|
+
return max;
|
|
6803
|
+
}, [processedData, allKeys]);
|
|
6804
|
+
const minDataValue = useMemo6(() => {
|
|
6805
|
+
let min = 0;
|
|
6806
|
+
const numericKeys = allKeys;
|
|
6807
|
+
for (const row of processedData) {
|
|
6808
|
+
const r = row;
|
|
6809
|
+
for (const key of numericKeys) {
|
|
6810
|
+
const v = r[key];
|
|
6811
|
+
if (typeof v === "number" && Number.isFinite(v) && v < min)
|
|
6812
|
+
min = v;
|
|
6813
|
+
}
|
|
6814
|
+
}
|
|
6815
|
+
return min;
|
|
6816
|
+
}, [processedData, allKeys]);
|
|
6817
|
+
const niceMax = useMemo6(() => {
|
|
6818
|
+
let padding = 0.08;
|
|
6819
|
+
if (maxDataValue > 1e6) padding = 0.05;
|
|
6820
|
+
if (maxDataValue > 1e7) padding = 0.03;
|
|
6821
|
+
if (maxDataValue === 0) padding = 0.12;
|
|
6822
|
+
const padded = maxDataValue * (1 + padding);
|
|
6823
|
+
return niceCeil(padded);
|
|
6824
|
+
}, [maxDataValue]);
|
|
6825
|
+
const computedWidth = useMemo6(() => {
|
|
6826
|
+
if (typeof width === "number") return width;
|
|
6827
|
+
const points = Math.max(1, processedData.length);
|
|
6828
|
+
const barCount = series?.bar?.length ?? 0;
|
|
6829
|
+
const lineCount = series?.line?.length ?? 0;
|
|
6830
|
+
const areaCount = series?.area?.length ?? 0;
|
|
6831
|
+
const basePerPoint = 60;
|
|
6832
|
+
const perBarExtra = barCount > 0 ? Math.max(0, barCount - 1) * 8 : 0;
|
|
6833
|
+
const perOtherExtra = (lineCount + areaCount) * 4;
|
|
6834
|
+
let sizeFactor = 1;
|
|
6835
|
+
if (niceMax > 1e5) sizeFactor = 1.1;
|
|
6836
|
+
if (niceMax > 1e6) sizeFactor = 1.2;
|
|
6837
|
+
if (niceMax > 1e7) sizeFactor = 1.3;
|
|
6838
|
+
const perPoint = Math.round(
|
|
6839
|
+
(basePerPoint + perBarExtra + perOtherExtra) * sizeFactor
|
|
6840
|
+
);
|
|
6841
|
+
const marginExtra = 120;
|
|
6842
|
+
const calculated = points * perPoint + marginExtra;
|
|
6843
|
+
const minWidth = 300;
|
|
6844
|
+
const maxWidth = 1800;
|
|
6845
|
+
return Math.max(minWidth, Math.min(maxWidth, calculated));
|
|
6846
|
+
}, [
|
|
6847
|
+
width,
|
|
6848
|
+
processedData.length,
|
|
6849
|
+
series?.bar?.length,
|
|
6850
|
+
series?.line?.length,
|
|
6851
|
+
series?.area?.length,
|
|
6852
|
+
niceMax
|
|
6853
|
+
]);
|
|
6854
|
+
const toggleTooltip = useCallback7(
|
|
6855
|
+
(tooltipId, data2, basePosition) => {
|
|
6856
|
+
const existingIndex = activeTooltips.findIndex((t) => t.id === tooltipId);
|
|
6857
|
+
if (existingIndex !== -1) {
|
|
6858
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== tooltipId));
|
|
6859
|
+
} else {
|
|
6860
|
+
if (activeTooltips.length >= maxTooltips) {
|
|
6861
|
+
toast2.warning(
|
|
6862
|
+
`Limite de ${maxTooltips} janelas de informa\xE7\xE3o atingido. A mais antiga ser\xE1 substitu\xEDda.`
|
|
6863
|
+
);
|
|
6864
|
+
}
|
|
6865
|
+
const offsetIndex = activeTooltips.length;
|
|
6866
|
+
const gap = 28;
|
|
6867
|
+
const newTooltip = {
|
|
6868
|
+
id: tooltipId,
|
|
6869
|
+
data: data2,
|
|
6870
|
+
position: {
|
|
6871
|
+
top: basePosition.top + offsetIndex * gap,
|
|
6872
|
+
left: basePosition.left + offsetIndex * gap
|
|
6873
|
+
}
|
|
6874
|
+
};
|
|
6875
|
+
setActiveTooltips((prev) => {
|
|
6876
|
+
const next = [...prev, newTooltip];
|
|
6877
|
+
return next.length > maxTooltips ? next.slice(1) : next;
|
|
6878
|
+
});
|
|
6879
|
+
}
|
|
6880
|
+
},
|
|
6881
|
+
[activeTooltips, maxTooltips]
|
|
6882
|
+
);
|
|
6883
|
+
const handleChartClick = useCallback7(
|
|
6884
|
+
(e) => {
|
|
6885
|
+
if (!enableDraggableTooltips) return;
|
|
6886
|
+
const ev = e;
|
|
6887
|
+
if (ev?.activePayload?.length) {
|
|
6888
|
+
const clickedData = ev.activePayload[0].payload;
|
|
6889
|
+
const xAxisValue = clickedData[xAxisConfig.dataKey] || clickedData.name || "N/A";
|
|
6890
|
+
const tooltipId = String(xAxisValue);
|
|
6891
|
+
toggleTooltip(tooltipId, clickedData, {
|
|
6892
|
+
top: (ev.chartY || 100) - 10,
|
|
6893
|
+
left: (ev.chartX || 100) - 100
|
|
6894
|
+
});
|
|
6895
|
+
} else {
|
|
6896
|
+
setActiveTooltips([]);
|
|
6897
|
+
}
|
|
6898
|
+
},
|
|
6899
|
+
[enableDraggableTooltips, xAxisConfig.dataKey, toggleTooltip]
|
|
6900
|
+
);
|
|
6901
|
+
const handleBarClick = useCallback7(
|
|
6902
|
+
(data2, index, event) => {
|
|
6903
|
+
if (!enableDraggableTooltips) return;
|
|
6904
|
+
event.stopPropagation();
|
|
6905
|
+
const xAxisValue = data2[xAxisConfig.dataKey] || "N/A";
|
|
6906
|
+
const tooltipId = String(xAxisValue);
|
|
6907
|
+
const rect = event.target.getBoundingClientRect();
|
|
6908
|
+
toggleTooltip(tooltipId, data2, {
|
|
6909
|
+
top: Math.max(8, rect.top - 10),
|
|
6910
|
+
left: rect.right + 10
|
|
6911
|
+
});
|
|
6912
|
+
},
|
|
6913
|
+
[enableDraggableTooltips, xAxisConfig.dataKey, toggleTooltip]
|
|
6914
|
+
);
|
|
6915
|
+
const handleSeriesClick = useCallback7(
|
|
6916
|
+
(...args) => {
|
|
6917
|
+
if (args.length >= 3) {
|
|
6918
|
+
const [data2, index, event] = args;
|
|
6919
|
+
handleBarClick(data2, index, event);
|
|
6920
|
+
return;
|
|
6921
|
+
}
|
|
6922
|
+
handleChartClick(args[0]);
|
|
6923
|
+
},
|
|
6924
|
+
[handleBarClick, handleChartClick]
|
|
6925
|
+
);
|
|
6926
|
+
const onTooltipPositionChange = useCallback7(
|
|
6927
|
+
(id, position) => {
|
|
6928
|
+
setActiveTooltips(
|
|
6929
|
+
(prev) => prev.map((t) => t.id === id ? { ...t, position } : t)
|
|
6930
|
+
);
|
|
6931
|
+
},
|
|
6932
|
+
[]
|
|
6933
|
+
);
|
|
6934
|
+
const titleClassName = useMemo6(
|
|
6935
|
+
() => "text-xl font-semibold text-foreground mb-3",
|
|
6936
|
+
[]
|
|
6937
|
+
);
|
|
6938
|
+
const finalEnableHighlights = enableHighlights;
|
|
6939
|
+
const finalEnableShowOnly = enableShowOnly;
|
|
6940
|
+
const finalEnablePeriodsDropdown = enablePeriodsDropdown && enableDraggableTooltips;
|
|
6941
|
+
const defaultChartRightMargin = 30;
|
|
6942
|
+
const defaultChartLeftMargin = 0;
|
|
6943
|
+
const containerPaddingLeft = 16;
|
|
6944
|
+
const finalChartRightMargin = chartMargin?.right ?? defaultChartRightMargin;
|
|
6945
|
+
const finalChartLeftMargin = chartMargin?.left ?? defaultChartLeftMargin;
|
|
6946
|
+
const finalChartTopMargin = chartMargin?.top ?? (showLabels ? 48 : 20);
|
|
6947
|
+
const finalChartBottomMargin = chartMargin?.bottom ?? 5;
|
|
6948
|
+
const measuredInner = measuredWidth ? Math.max(0, measuredWidth - 32) : void 0;
|
|
6949
|
+
const effectiveChartWidth = typeof width === "number" ? width : measuredInner ?? computedWidth;
|
|
6950
|
+
const chartInnerWidth = effectiveChartWidth - finalChartLeftMargin - finalChartRightMargin;
|
|
6951
|
+
const openTooltipForPeriod = useCallback7(
|
|
6952
|
+
(periodName) => {
|
|
6953
|
+
if (!enableDraggableTooltips) return;
|
|
6954
|
+
const row = processedData.find((r) => String(r.name) === periodName);
|
|
6955
|
+
if (!row) return;
|
|
6956
|
+
const tooltipId = String(periodName);
|
|
6957
|
+
const existingIndex = activeTooltips.findIndex((t) => t.id === tooltipId);
|
|
6958
|
+
if (existingIndex !== -1) {
|
|
6959
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== tooltipId));
|
|
6960
|
+
return;
|
|
6961
|
+
}
|
|
6962
|
+
if (activeTooltips.length >= maxTooltips) {
|
|
6963
|
+
toast2.warning(
|
|
6964
|
+
`Limite de ${maxTooltips} janelas de informa\xE7\xE3o atingido. A mais antiga ser\xE1 substitu\xEDda.`
|
|
6965
|
+
);
|
|
6966
|
+
}
|
|
6967
|
+
const offsetIndex = activeTooltips.length;
|
|
6968
|
+
const availableWidth = typeof width === "number" ? width : measuredInner ?? computedWidth;
|
|
6969
|
+
const gap = 28;
|
|
6970
|
+
const leftGap = 28;
|
|
6971
|
+
const newTooltip = {
|
|
6972
|
+
id: tooltipId,
|
|
6973
|
+
data: row,
|
|
6974
|
+
position: {
|
|
6975
|
+
top: 48 + offsetIndex * gap,
|
|
6976
|
+
left: Math.max(120, availableWidth - 280 - offsetIndex * leftGap)
|
|
6977
|
+
}
|
|
6978
|
+
};
|
|
6979
|
+
setActiveTooltips((prev) => {
|
|
6980
|
+
const next = [...prev, newTooltip];
|
|
6981
|
+
return next.length > maxTooltips ? next.slice(1) : next;
|
|
6982
|
+
});
|
|
6983
|
+
},
|
|
6984
|
+
[
|
|
6985
|
+
enableDraggableTooltips,
|
|
6986
|
+
processedData,
|
|
6987
|
+
activeTooltips,
|
|
6988
|
+
width,
|
|
6989
|
+
measuredInner,
|
|
6990
|
+
computedWidth,
|
|
6991
|
+
maxTooltips
|
|
6992
|
+
]
|
|
6993
|
+
);
|
|
6994
|
+
if (!data) return null;
|
|
6995
|
+
if (Array.isArray(data) && data.length === 0) {
|
|
6996
|
+
return /* @__PURE__ */ jsx57(
|
|
6997
|
+
"div",
|
|
6998
|
+
{
|
|
6999
|
+
className: cn(
|
|
7000
|
+
"rounded-lg bg-card p-4 relative w-full text-muted-foreground"
|
|
7001
|
+
),
|
|
7002
|
+
children: /* @__PURE__ */ jsx57(
|
|
7003
|
+
"div",
|
|
7004
|
+
{
|
|
7005
|
+
style: {
|
|
7006
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`
|
|
7007
|
+
},
|
|
7008
|
+
children: "Sem dados para exibir"
|
|
7009
|
+
}
|
|
7010
|
+
)
|
|
7011
|
+
}
|
|
7012
|
+
);
|
|
7013
|
+
}
|
|
7014
|
+
return /* @__PURE__ */ jsx57(
|
|
7015
|
+
"div",
|
|
7016
|
+
{
|
|
7017
|
+
ref: wrapperRef,
|
|
7018
|
+
style: {
|
|
7019
|
+
width: "100%",
|
|
7020
|
+
overflowX: "hidden",
|
|
7021
|
+
overflowY: "hidden",
|
|
7022
|
+
minWidth: 0
|
|
7023
|
+
},
|
|
7024
|
+
children: /* @__PURE__ */ jsxs39(
|
|
7025
|
+
"div",
|
|
7026
|
+
{
|
|
7027
|
+
className: cn("rounded-lg bg-card p-2 relative", className),
|
|
7028
|
+
style: { width: "100%", maxWidth: "100%", minWidth: 0 },
|
|
7029
|
+
children: [
|
|
7030
|
+
title && /* @__PURE__ */ jsx57(
|
|
7031
|
+
"div",
|
|
7032
|
+
{
|
|
7033
|
+
style: {
|
|
7034
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`,
|
|
7035
|
+
width: "100%",
|
|
7036
|
+
maxWidth: `${chartInnerWidth}px`,
|
|
7037
|
+
display: "flex",
|
|
7038
|
+
justifyContent: titlePosition === "center" ? "center" : titlePosition === "right" ? "flex-end" : "flex-start",
|
|
7039
|
+
alignItems: "center",
|
|
7040
|
+
marginTop: 4
|
|
7041
|
+
},
|
|
7042
|
+
children: /* @__PURE__ */ jsx57("h3", { className: titleClassName, children: title })
|
|
7043
|
+
}
|
|
7044
|
+
),
|
|
7045
|
+
allKeys.length > 0 && (finalEnableHighlights || finalEnableShowOnly) && /* @__PURE__ */ jsxs39(
|
|
7046
|
+
"div",
|
|
7047
|
+
{
|
|
7048
|
+
className: "flex items-center w-full",
|
|
7049
|
+
style: {
|
|
7050
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`,
|
|
7051
|
+
width: "98%",
|
|
7052
|
+
display: "flex",
|
|
7053
|
+
alignItems: "center",
|
|
7054
|
+
gap: "0.5rem"
|
|
7055
|
+
},
|
|
7056
|
+
children: [
|
|
7057
|
+
finalEnableHighlights && /* @__PURE__ */ jsx57(
|
|
7058
|
+
Highlights_default,
|
|
7059
|
+
{
|
|
7060
|
+
allKeys,
|
|
7061
|
+
mapperConfig,
|
|
7062
|
+
finalColors,
|
|
7063
|
+
highlightedSeries,
|
|
7064
|
+
toggleHighlight,
|
|
7065
|
+
containerWidth: chartInnerWidth
|
|
7066
|
+
}
|
|
7067
|
+
),
|
|
7068
|
+
finalEnableShowOnly && /* @__PURE__ */ jsx57(
|
|
7069
|
+
ShowOnly_default,
|
|
7070
|
+
{
|
|
7071
|
+
showOnlyHighlighted,
|
|
7072
|
+
setShowOnlyHighlighted,
|
|
7073
|
+
highlightedSeriesSize: highlightedSeries.size,
|
|
7074
|
+
clearHighlights: () => setHighlightedSeries(/* @__PURE__ */ new Set())
|
|
7075
|
+
}
|
|
7076
|
+
),
|
|
7077
|
+
finalEnablePeriodsDropdown && /* @__PURE__ */ jsx57(
|
|
7078
|
+
"div",
|
|
7079
|
+
{
|
|
7080
|
+
style: {
|
|
7081
|
+
marginLeft: "auto",
|
|
7082
|
+
display: "flex",
|
|
7083
|
+
alignItems: "center"
|
|
7084
|
+
},
|
|
7085
|
+
children: /* @__PURE__ */ jsx57(
|
|
7086
|
+
PeriodsDropdown_default,
|
|
7087
|
+
{
|
|
7088
|
+
processedData,
|
|
7089
|
+
onOpenPeriod: openTooltipForPeriod,
|
|
7090
|
+
rightOffset: finalChartRightMargin,
|
|
7091
|
+
activePeriods
|
|
7092
|
+
}
|
|
7093
|
+
)
|
|
7094
|
+
}
|
|
7095
|
+
)
|
|
7096
|
+
]
|
|
7097
|
+
}
|
|
7098
|
+
),
|
|
7099
|
+
!(allKeys.length > 0 && (finalEnableHighlights || finalEnableShowOnly)) && finalEnablePeriodsDropdown && /* @__PURE__ */ jsx57(
|
|
7100
|
+
"div",
|
|
7101
|
+
{
|
|
7102
|
+
style: {
|
|
7103
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`,
|
|
7104
|
+
paddingRight: `${finalChartRightMargin}px`,
|
|
7105
|
+
width: "100%",
|
|
7106
|
+
maxWidth: `${chartInnerWidth}px`,
|
|
7107
|
+
display: "flex",
|
|
7108
|
+
justifyContent: "flex-end"
|
|
7109
|
+
},
|
|
7110
|
+
children: /* @__PURE__ */ jsx57(
|
|
7111
|
+
PeriodsDropdown_default,
|
|
7112
|
+
{
|
|
7113
|
+
processedData,
|
|
7114
|
+
onOpenPeriod: openTooltipForPeriod,
|
|
7115
|
+
rightOffset: finalChartRightMargin
|
|
7116
|
+
}
|
|
7117
|
+
)
|
|
7118
|
+
}
|
|
7119
|
+
),
|
|
7120
|
+
/* @__PURE__ */ jsx57(ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ jsxs39(
|
|
7121
|
+
ComposedChart,
|
|
7122
|
+
{
|
|
7123
|
+
data: processedData,
|
|
7124
|
+
height,
|
|
7125
|
+
margin: {
|
|
7126
|
+
top: finalChartTopMargin,
|
|
7127
|
+
right: finalChartRightMargin,
|
|
7128
|
+
left: finalChartLeftMargin,
|
|
7129
|
+
bottom: finalChartBottomMargin
|
|
7130
|
+
},
|
|
7131
|
+
onClick: handleChartClick,
|
|
7132
|
+
children: [
|
|
7133
|
+
showGrid && /* @__PURE__ */ jsx57(
|
|
7134
|
+
CartesianGrid,
|
|
7135
|
+
{
|
|
7136
|
+
strokeDasharray: "3 3",
|
|
7137
|
+
stroke: gridColor || "hsl(var(--muted-foreground))",
|
|
7138
|
+
opacity: 0.5
|
|
7139
|
+
}
|
|
7140
|
+
),
|
|
7141
|
+
/* @__PURE__ */ jsx57(
|
|
7142
|
+
XAxis,
|
|
7143
|
+
{
|
|
7144
|
+
dataKey: xAxisConfig.dataKey,
|
|
7145
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7146
|
+
fontSize: 12,
|
|
7147
|
+
tickLine: false,
|
|
7148
|
+
axisLine: false,
|
|
7149
|
+
tickFormatter: xAxisConfig.formatter
|
|
7150
|
+
}
|
|
7151
|
+
),
|
|
7152
|
+
/* @__PURE__ */ jsx57(
|
|
7153
|
+
YAxis,
|
|
7154
|
+
{
|
|
7155
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7156
|
+
fontSize: 12,
|
|
7157
|
+
tickLine: false,
|
|
7158
|
+
axisLine: false,
|
|
7159
|
+
tickFormatter: (value) => Number(value).toLocaleString("pt-BR"),
|
|
7160
|
+
domain: [Math.min(minDataValue, 0), niceMax],
|
|
7161
|
+
tickCount: 6
|
|
7162
|
+
}
|
|
7163
|
+
),
|
|
7164
|
+
minDataValue < 0 && /* @__PURE__ */ jsx57(
|
|
7165
|
+
ReferenceLine,
|
|
7166
|
+
{
|
|
7167
|
+
y: 0,
|
|
7168
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7169
|
+
strokeWidth: 1,
|
|
7170
|
+
strokeDasharray: "4 4"
|
|
7171
|
+
}
|
|
7172
|
+
),
|
|
7173
|
+
showTooltip && /* @__PURE__ */ jsx57(
|
|
7174
|
+
Tooltip,
|
|
7175
|
+
{
|
|
7176
|
+
content: showTooltipTotal ? /* @__PURE__ */ jsx57(TooltipWithTotal_default, { finalColors }) : /* @__PURE__ */ jsx57(TooltipSimple_default, { finalColors }),
|
|
7177
|
+
cursor: { fill: "hsl(var(--muted))", opacity: 0.1 }
|
|
7178
|
+
}
|
|
7179
|
+
),
|
|
7180
|
+
showLegend && /* @__PURE__ */ jsx57(
|
|
7181
|
+
Legend,
|
|
7182
|
+
{
|
|
7183
|
+
wrapperStyle: {
|
|
7184
|
+
color: "hsl(var(--foreground))",
|
|
7185
|
+
fontSize: "14px"
|
|
7186
|
+
}
|
|
7187
|
+
}
|
|
7188
|
+
),
|
|
7189
|
+
seriesOrder.map((s) => {
|
|
7190
|
+
const key = s.key;
|
|
7191
|
+
if (showOnlyHighlighted && !highlightedSeries.has(key))
|
|
7192
|
+
return null;
|
|
7193
|
+
const label = mapperConfig[key]?.label ?? labelMap?.[key] ?? formatFieldName(key);
|
|
7194
|
+
const color = finalColors[key];
|
|
7195
|
+
if (s.type === "bar") {
|
|
7196
|
+
return /* @__PURE__ */ jsx57(
|
|
7197
|
+
Bar,
|
|
7198
|
+
{
|
|
7199
|
+
dataKey: key,
|
|
7200
|
+
name: label,
|
|
7201
|
+
fill: color,
|
|
7202
|
+
radius: [4, 4, 0, 0],
|
|
7203
|
+
onClick: handleBarClick,
|
|
7204
|
+
style: {
|
|
7205
|
+
cursor: "pointer",
|
|
7206
|
+
opacity: highlightedSeries.size > 0 ? highlightedSeries.has(key) ? 1 : 0.25 : 1
|
|
7207
|
+
},
|
|
7208
|
+
activeBar: /* @__PURE__ */ jsx57(
|
|
7209
|
+
Rectangle,
|
|
7210
|
+
{
|
|
7211
|
+
fill: color,
|
|
7212
|
+
stroke: color,
|
|
7213
|
+
strokeWidth: 2,
|
|
7214
|
+
opacity: 0.8
|
|
7215
|
+
}
|
|
7216
|
+
),
|
|
7217
|
+
children: showLabels && highlightedSeries.size === 0 || highlightedSeries.has(key) ? /* @__PURE__ */ jsx57(
|
|
7218
|
+
LabelList,
|
|
7219
|
+
{
|
|
7220
|
+
dataKey: key,
|
|
7221
|
+
position: "top",
|
|
7222
|
+
content: pillLabelRenderer_default(color, "filled"),
|
|
7223
|
+
offset: 8
|
|
7224
|
+
}
|
|
7225
|
+
) : null
|
|
7226
|
+
},
|
|
7227
|
+
`bar-${key}`
|
|
7228
|
+
);
|
|
7229
|
+
}
|
|
7230
|
+
if (s.type === "line") {
|
|
7231
|
+
return /* @__PURE__ */ jsx57(
|
|
7232
|
+
Line,
|
|
7233
|
+
{
|
|
7234
|
+
dataKey: key,
|
|
7235
|
+
name: label,
|
|
7236
|
+
stroke: color,
|
|
7237
|
+
strokeWidth: 2,
|
|
7238
|
+
dot: { r: 3 },
|
|
7239
|
+
activeDot: { r: 6 },
|
|
7240
|
+
onClick: handleSeriesClick,
|
|
7241
|
+
style: {
|
|
7242
|
+
cursor: "pointer",
|
|
7243
|
+
pointerEvents: "all",
|
|
7244
|
+
opacity: highlightedSeries.size > 0 ? highlightedSeries.has(key) ? 1 : 0.25 : 1
|
|
7245
|
+
},
|
|
7246
|
+
children: showLabels && highlightedSeries.size === 0 || highlightedSeries.has(key) ? /* @__PURE__ */ jsx57(
|
|
7247
|
+
LabelList,
|
|
7248
|
+
{
|
|
7249
|
+
dataKey: key,
|
|
7250
|
+
position: "top",
|
|
7251
|
+
content: pillLabelRenderer_default(color, "filled"),
|
|
7252
|
+
offset: 14
|
|
7253
|
+
}
|
|
7254
|
+
) : null
|
|
7255
|
+
},
|
|
7256
|
+
`line-${key}`
|
|
7257
|
+
);
|
|
7258
|
+
}
|
|
7259
|
+
if (s.type === "area") {
|
|
7260
|
+
return /* @__PURE__ */ jsx57(
|
|
7261
|
+
Area,
|
|
7262
|
+
{
|
|
7263
|
+
dataKey: key,
|
|
7264
|
+
name: label,
|
|
7265
|
+
stroke: color,
|
|
7266
|
+
fill: color,
|
|
7267
|
+
fillOpacity: 0.35,
|
|
7268
|
+
strokeWidth: 2,
|
|
7269
|
+
onClick: handleSeriesClick,
|
|
7270
|
+
style: {
|
|
7271
|
+
cursor: "pointer",
|
|
7272
|
+
pointerEvents: "all",
|
|
7273
|
+
opacity: highlightedSeries.size > 0 ? highlightedSeries.has(key) ? 1 : 0.25 : 1
|
|
7274
|
+
},
|
|
7275
|
+
children: showLabels && highlightedSeries.size === 0 || highlightedSeries.has(key) ? /* @__PURE__ */ jsx57(
|
|
7276
|
+
LabelList,
|
|
7277
|
+
{
|
|
7278
|
+
dataKey: key,
|
|
7279
|
+
position: "top",
|
|
7280
|
+
content: pillLabelRenderer_default(color, "soft"),
|
|
7281
|
+
offset: 12
|
|
7282
|
+
}
|
|
7283
|
+
) : null
|
|
7284
|
+
},
|
|
7285
|
+
`area-${key}`
|
|
7286
|
+
);
|
|
7287
|
+
}
|
|
7288
|
+
return null;
|
|
7289
|
+
})
|
|
7290
|
+
]
|
|
7291
|
+
}
|
|
7292
|
+
) }),
|
|
7293
|
+
enableDraggableTooltips && activeTooltips.map((tooltip) => /* @__PURE__ */ jsx57(
|
|
7294
|
+
DraggableTooltip_default,
|
|
7295
|
+
{
|
|
7296
|
+
id: tooltip.id,
|
|
7297
|
+
data: adaptDataForTooltip(tooltip.data),
|
|
7298
|
+
position: tooltip.position,
|
|
7299
|
+
title,
|
|
7300
|
+
dataKeys: allKeys,
|
|
7301
|
+
finalColors,
|
|
7302
|
+
highlightedSeries,
|
|
7303
|
+
toggleHighlight,
|
|
7304
|
+
showOnlyHighlighted,
|
|
7305
|
+
onClose: (id) => setActiveTooltips((prev) => prev.filter((t) => t.id !== id)),
|
|
7306
|
+
onPositionChange: onTooltipPositionChange,
|
|
7307
|
+
periodLabel: "Per\xEDodo Selecionado",
|
|
7308
|
+
dataLabel: "Dados do Per\xEDodo",
|
|
7309
|
+
globalTooltipCount: activeTooltips.length,
|
|
7310
|
+
onCloseAll: () => window.dispatchEvent(new Event("closeAllTooltips")),
|
|
7311
|
+
closeAllButtonPosition: "top-center",
|
|
7312
|
+
closeAllButtonVariant: "floating"
|
|
7313
|
+
},
|
|
7314
|
+
tooltip.id
|
|
7315
|
+
)),
|
|
7316
|
+
enableDraggableTooltips && activeTooltips.length > 1 && /* @__PURE__ */ jsx57(
|
|
7317
|
+
CloseAllButton_default,
|
|
7318
|
+
{
|
|
7319
|
+
count: activeTooltips.length,
|
|
7320
|
+
onCloseAll: () => window.dispatchEvent(new Event("closeAllTooltips")),
|
|
7321
|
+
position: "top-center",
|
|
7322
|
+
variant: "floating"
|
|
7323
|
+
}
|
|
7324
|
+
)
|
|
7325
|
+
]
|
|
7326
|
+
}
|
|
7327
|
+
)
|
|
7328
|
+
}
|
|
7329
|
+
);
|
|
7330
|
+
};
|
|
7331
|
+
var Chart_default = Chart;
|
|
7332
|
+
|
|
7333
|
+
// src/components/charts/BarChart.tsx
|
|
7334
|
+
import { useState as useState12, useEffect as useEffect11, useCallback as useCallback8, useMemo as useMemo7 } from "react";
|
|
7335
|
+
import {
|
|
7336
|
+
BarChart as RechartsBarChart,
|
|
7337
|
+
Bar as Bar2,
|
|
7338
|
+
Rectangle as Rectangle2,
|
|
7339
|
+
XAxis as XAxis2,
|
|
7340
|
+
YAxis as YAxis2,
|
|
7341
|
+
CartesianGrid as CartesianGrid2,
|
|
7342
|
+
Tooltip as Tooltip2,
|
|
7343
|
+
Legend as Legend2,
|
|
7344
|
+
LabelList as LabelList2
|
|
7345
|
+
} from "recharts";
|
|
7346
|
+
import { jsx as jsx58, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
7347
|
+
var DEFAULT_COLORS2 = ["#55af7d", "#8e68ff", "#2273e1"];
|
|
7348
|
+
var BarChart = ({
|
|
7349
|
+
data,
|
|
7350
|
+
className,
|
|
7351
|
+
height = 350,
|
|
7352
|
+
width = 900,
|
|
7353
|
+
colors: colors2 = DEFAULT_COLORS2,
|
|
7354
|
+
gridColor,
|
|
7355
|
+
showGrid = true,
|
|
7356
|
+
showTooltip = true,
|
|
7357
|
+
showLegend = true,
|
|
7358
|
+
title,
|
|
7359
|
+
titlePosition = "left",
|
|
7360
|
+
showLabels = false,
|
|
7361
|
+
xAxis,
|
|
7362
|
+
mapper,
|
|
7363
|
+
yAxis,
|
|
7364
|
+
labelMap,
|
|
7365
|
+
autoDetect = false,
|
|
7366
|
+
padding,
|
|
7367
|
+
margins,
|
|
7368
|
+
containerPaddingLeft,
|
|
7369
|
+
chartMargins
|
|
7370
|
+
}) => {
|
|
7371
|
+
const resolvedContainerPaddingLeft = resolveContainerPaddingLeft(
|
|
7372
|
+
padding,
|
|
7373
|
+
containerPaddingLeft,
|
|
7374
|
+
16
|
|
7375
|
+
);
|
|
7376
|
+
const smartConfig = useMemo7(() => {
|
|
7377
|
+
const providedMapper = yAxis ?? mapper;
|
|
7378
|
+
if (autoDetect === true || xAxis == null || providedMapper == null) {
|
|
7379
|
+
const detectedXAxis = detectXAxis(data);
|
|
7380
|
+
const detectedFields = detectDataFields(data, detectedXAxis);
|
|
7381
|
+
return {
|
|
7382
|
+
xAxisConfig: {
|
|
7383
|
+
dataKey: detectedXAxis,
|
|
7384
|
+
label: labelMap?.[detectedXAxis] ?? formatFieldName(detectedXAxis),
|
|
7385
|
+
autoLabel: true
|
|
7386
|
+
},
|
|
7387
|
+
mapperConfig: detectedFields.reduce((acc, field) => {
|
|
7388
|
+
acc[field] = {
|
|
7389
|
+
label: labelMap?.[field] ?? formatFieldName(field),
|
|
7390
|
+
type: "number",
|
|
7391
|
+
visible: true
|
|
7392
|
+
};
|
|
7393
|
+
return acc;
|
|
7394
|
+
}, {})
|
|
7395
|
+
};
|
|
7396
|
+
}
|
|
7397
|
+
const xAxisConfig2 = typeof xAxis === "string" ? { dataKey: xAxis, label: formatFieldName(xAxis), autoLabel: true } : xAxis;
|
|
7398
|
+
let mapperConfig2;
|
|
7399
|
+
if (Array.isArray(providedMapper)) {
|
|
7400
|
+
mapperConfig2 = providedMapper.reduce((acc, field) => {
|
|
7401
|
+
acc[field] = {
|
|
7402
|
+
label: labelMap?.[field] ?? formatFieldName(field),
|
|
7403
|
+
type: "auto",
|
|
7404
|
+
visible: true
|
|
7405
|
+
};
|
|
7406
|
+
return acc;
|
|
7407
|
+
}, {});
|
|
7408
|
+
} else {
|
|
7409
|
+
mapperConfig2 = Object.keys(providedMapper).reduce(
|
|
7410
|
+
(acc, key) => {
|
|
7411
|
+
acc[key] = {
|
|
7412
|
+
label: providedMapper[key]?.label ?? labelMap?.[key] ?? formatFieldName(key),
|
|
7413
|
+
type: "auto",
|
|
7414
|
+
visible: true,
|
|
7415
|
+
...providedMapper[key]
|
|
7416
|
+
// Sobrescreve com configurações do usuário
|
|
7417
|
+
};
|
|
7418
|
+
return acc;
|
|
7419
|
+
},
|
|
7420
|
+
{}
|
|
7421
|
+
);
|
|
7422
|
+
}
|
|
7423
|
+
return { xAxisConfig: xAxisConfig2, mapperConfig: mapperConfig2 };
|
|
7424
|
+
}, [data, xAxis, mapper, yAxis, autoDetect, labelMap]);
|
|
7425
|
+
const { xAxisConfig, mapperConfig } = smartConfig;
|
|
7426
|
+
const [activeTooltips, setActiveTooltips] = useState12([]);
|
|
7427
|
+
const [isDragging, setIsDragging] = useState12(null);
|
|
7428
|
+
const [dragOffset, setDragOffset] = useState12({
|
|
7429
|
+
x: 0,
|
|
7430
|
+
y: 0
|
|
7431
|
+
});
|
|
7432
|
+
const [globalTooltipCount, setGlobalTooltipCount] = useState12(0);
|
|
7433
|
+
const [alignmentGuides, setAlignmentGuides] = useState12([]);
|
|
7434
|
+
const processedData = data.map((item) => ({
|
|
7435
|
+
...item,
|
|
7436
|
+
name: String(item[xAxisConfig.dataKey] || "N/A")
|
|
7437
|
+
// Garantir propriedade 'name' para tooltip
|
|
7438
|
+
}));
|
|
7439
|
+
const generateColors = (dataKeys2) => {
|
|
7440
|
+
const colorMap = {};
|
|
7441
|
+
const allColors = generateAdditionalColors(colors2, dataKeys2.length);
|
|
7442
|
+
dataKeys2.forEach((key, index) => {
|
|
7443
|
+
colorMap[key] = allColors[index] || colors2[index % colors2.length];
|
|
7444
|
+
});
|
|
7445
|
+
return colorMap;
|
|
7446
|
+
};
|
|
7447
|
+
const dataKeys = Object.keys(mapperConfig);
|
|
7448
|
+
const finalColors = generateColors(dataKeys);
|
|
7449
|
+
const adaptDataForTooltip = (universalData) => {
|
|
7450
|
+
return {
|
|
7451
|
+
...universalData,
|
|
7452
|
+
name: String(universalData[xAxisConfig.dataKey] || "N/A")
|
|
7453
|
+
// Garantir que tem a propriedade 'name'
|
|
7454
|
+
};
|
|
7455
|
+
};
|
|
7456
|
+
const maxDataValue = useMemo7(() => {
|
|
7457
|
+
let max = 0;
|
|
7458
|
+
const keys = Object.keys(mapperConfig);
|
|
7459
|
+
for (const row of processedData) {
|
|
7460
|
+
const r = row;
|
|
7461
|
+
for (const key of keys) {
|
|
7462
|
+
const v = r[key];
|
|
7463
|
+
if (typeof v === "number" && Number.isFinite(v) && v > max)
|
|
7464
|
+
max = v;
|
|
7465
|
+
}
|
|
7466
|
+
}
|
|
7467
|
+
return max;
|
|
7468
|
+
}, [processedData, mapperConfig]);
|
|
7469
|
+
const niceMax = useMemo7(() => {
|
|
7470
|
+
let padding2 = 0.08;
|
|
7471
|
+
if (maxDataValue > 1e6) padding2 = 0.05;
|
|
7472
|
+
if (maxDataValue > 1e7) padding2 = 0.03;
|
|
7473
|
+
if (maxDataValue === 0) padding2 = 0.12;
|
|
7474
|
+
const padded = maxDataValue * (1 + padding2);
|
|
7475
|
+
return niceCeil(padded);
|
|
7476
|
+
}, [maxDataValue]);
|
|
7477
|
+
const handleBarClick = (data2, index, event) => {
|
|
7478
|
+
event.stopPropagation();
|
|
7479
|
+
const xAxisValue = data2[xAxisConfig.dataKey] || "N/A";
|
|
7480
|
+
const tooltipId = `${xAxisValue}`;
|
|
7481
|
+
const rect = event.target.getBoundingClientRect();
|
|
7482
|
+
const existingIndex = activeTooltips.findIndex(
|
|
7483
|
+
(tooltip) => tooltip.id === tooltipId
|
|
7484
|
+
);
|
|
7485
|
+
if (existingIndex !== -1) {
|
|
7486
|
+
setActiveTooltips(
|
|
7487
|
+
(prev) => prev.filter((tooltip) => tooltip.id !== tooltipId)
|
|
7488
|
+
);
|
|
7489
|
+
} else {
|
|
7490
|
+
const newTooltip = {
|
|
7491
|
+
id: tooltipId,
|
|
7492
|
+
data: data2,
|
|
7493
|
+
position: {
|
|
7494
|
+
top: rect.top - 10,
|
|
7495
|
+
// Posição fixa da viewport
|
|
7496
|
+
left: rect.right + 10
|
|
7497
|
+
// À direita da barra clicada
|
|
7498
|
+
}
|
|
7499
|
+
};
|
|
7500
|
+
setActiveTooltips((prev) => [...prev, newTooltip]);
|
|
7501
|
+
}
|
|
7502
|
+
};
|
|
7503
|
+
const handleChartClick = () => {
|
|
7504
|
+
setActiveTooltips([]);
|
|
7505
|
+
};
|
|
7506
|
+
const ALIGNMENT_THRESHOLD2 = 25;
|
|
7507
|
+
const GUIDE_THRESHOLD2 = 60;
|
|
7508
|
+
const STRONG_SNAP_THRESHOLD2 = 35;
|
|
7509
|
+
const PRECISION_SNAP_THRESHOLD2 = 8;
|
|
7510
|
+
const updateAlignmentGuides = useCallback8(
|
|
7511
|
+
(draggedTooltipId, currentPosition) => {
|
|
7512
|
+
if (!isDragging) return;
|
|
7513
|
+
const getAllTooltips = () => {
|
|
7514
|
+
const allTooltips2 = [];
|
|
7515
|
+
allTooltips2.push(...activeTooltips);
|
|
7516
|
+
const globalEvent = new CustomEvent("requestGlobalTooltips", {
|
|
7517
|
+
detail: { requesterId: draggedTooltipId, response: allTooltips2 }
|
|
7518
|
+
});
|
|
7519
|
+
window.dispatchEvent(globalEvent);
|
|
7520
|
+
return allTooltips2;
|
|
7521
|
+
};
|
|
7522
|
+
const allTooltips = getAllTooltips();
|
|
7523
|
+
const otherTooltips = allTooltips.filter(
|
|
7524
|
+
(t) => t.id !== draggedTooltipId
|
|
7525
|
+
);
|
|
7526
|
+
const guides = [];
|
|
7527
|
+
const tooltipDimensions = { width: 224, height: 120 };
|
|
7528
|
+
otherTooltips.forEach((tooltip) => {
|
|
7529
|
+
const topDiff = Math.abs(currentPosition.top - tooltip.position.top);
|
|
7530
|
+
if (topDiff <= GUIDE_THRESHOLD2) {
|
|
7531
|
+
guides.push({
|
|
7532
|
+
type: "horizontal",
|
|
7533
|
+
position: tooltip.position.top,
|
|
7534
|
+
visible: true,
|
|
7535
|
+
sourceTooltip: {
|
|
7536
|
+
top: currentPosition.top,
|
|
7537
|
+
left: currentPosition.left,
|
|
7538
|
+
width: tooltipDimensions.width,
|
|
7539
|
+
height: tooltipDimensions.height
|
|
7540
|
+
},
|
|
7541
|
+
targetTooltip: {
|
|
7542
|
+
top: tooltip.position.top,
|
|
7543
|
+
left: tooltip.position.left,
|
|
7544
|
+
width: tooltipDimensions.width,
|
|
7545
|
+
height: tooltipDimensions.height
|
|
7546
|
+
}
|
|
7547
|
+
});
|
|
7548
|
+
}
|
|
7549
|
+
const leftDiff = Math.abs(currentPosition.left - tooltip.position.left);
|
|
7550
|
+
if (leftDiff <= GUIDE_THRESHOLD2) {
|
|
7551
|
+
guides.push({
|
|
7552
|
+
type: "vertical",
|
|
7553
|
+
position: tooltip.position.left,
|
|
7554
|
+
visible: true,
|
|
7555
|
+
sourceTooltip: {
|
|
7556
|
+
top: currentPosition.top,
|
|
7557
|
+
left: currentPosition.left,
|
|
7558
|
+
width: tooltipDimensions.width,
|
|
7559
|
+
height: tooltipDimensions.height
|
|
7560
|
+
},
|
|
7561
|
+
targetTooltip: {
|
|
7562
|
+
top: tooltip.position.top,
|
|
7563
|
+
left: tooltip.position.left,
|
|
7564
|
+
width: tooltipDimensions.width,
|
|
7565
|
+
height: tooltipDimensions.height
|
|
7566
|
+
}
|
|
7567
|
+
});
|
|
7568
|
+
}
|
|
7569
|
+
});
|
|
7570
|
+
setAlignmentGuides(guides);
|
|
7571
|
+
},
|
|
7572
|
+
[isDragging, activeTooltips]
|
|
7573
|
+
);
|
|
7574
|
+
const snapToGuides = useCallback8(
|
|
7575
|
+
(position) => {
|
|
7576
|
+
const snappedPosition = { ...position };
|
|
7577
|
+
let hasSnapped = false;
|
|
7578
|
+
alignmentGuides.forEach((guide) => {
|
|
7579
|
+
if (guide.type === "horizontal") {
|
|
7580
|
+
const diff = Math.abs(position.top - guide.position);
|
|
7581
|
+
if (diff <= PRECISION_SNAP_THRESHOLD2) {
|
|
7582
|
+
snappedPosition.top = guide.position;
|
|
7583
|
+
hasSnapped = true;
|
|
7584
|
+
}
|
|
7585
|
+
} else if (guide.type === "vertical") {
|
|
7586
|
+
const diff = Math.abs(position.left - guide.position);
|
|
7587
|
+
if (diff <= PRECISION_SNAP_THRESHOLD2) {
|
|
7588
|
+
snappedPosition.left = guide.position;
|
|
7589
|
+
hasSnapped = true;
|
|
7590
|
+
}
|
|
7591
|
+
}
|
|
7592
|
+
});
|
|
7593
|
+
if (!hasSnapped) {
|
|
7594
|
+
alignmentGuides.forEach((guide) => {
|
|
7595
|
+
if (guide.type === "horizontal") {
|
|
7596
|
+
const diff = Math.abs(position.top - guide.position);
|
|
7597
|
+
if (diff <= STRONG_SNAP_THRESHOLD2) {
|
|
7598
|
+
snappedPosition.top = guide.position;
|
|
7599
|
+
}
|
|
7600
|
+
} else if (guide.type === "vertical") {
|
|
7601
|
+
const diff = Math.abs(position.left - guide.position);
|
|
7602
|
+
if (diff <= STRONG_SNAP_THRESHOLD2) {
|
|
7603
|
+
snappedPosition.left = guide.position;
|
|
7604
|
+
}
|
|
7605
|
+
}
|
|
7606
|
+
});
|
|
7607
|
+
}
|
|
7608
|
+
alignmentGuides.forEach((guide) => {
|
|
7609
|
+
if (guide.type === "horizontal") {
|
|
7610
|
+
const diff = Math.abs(position.top - guide.position);
|
|
7611
|
+
if (diff <= ALIGNMENT_THRESHOLD2 && snappedPosition.top === position.top) {
|
|
7612
|
+
snappedPosition.top = guide.position;
|
|
7613
|
+
}
|
|
7614
|
+
} else if (guide.type === "vertical") {
|
|
7615
|
+
const diff = Math.abs(position.left - guide.position);
|
|
7616
|
+
if (diff <= ALIGNMENT_THRESHOLD2 && snappedPosition.left === position.left) {
|
|
7617
|
+
snappedPosition.left = guide.position;
|
|
7618
|
+
}
|
|
7619
|
+
}
|
|
7620
|
+
});
|
|
7621
|
+
return snappedPosition;
|
|
7622
|
+
},
|
|
7623
|
+
[alignmentGuides]
|
|
7624
|
+
);
|
|
7625
|
+
const handleMouseDown = (e, tooltipId) => {
|
|
7626
|
+
e.preventDefault();
|
|
7627
|
+
e.stopPropagation();
|
|
7628
|
+
const tooltip = activeTooltips.find((t) => t.id === tooltipId);
|
|
7629
|
+
if (!tooltip) return;
|
|
7630
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
7631
|
+
const offsetX = e.clientX - rect.left;
|
|
7632
|
+
const offsetY = e.clientY - rect.top;
|
|
7633
|
+
setIsDragging(tooltipId);
|
|
7634
|
+
setDragOffset({ x: offsetX, y: offsetY });
|
|
7635
|
+
};
|
|
7636
|
+
useEffect11(() => {
|
|
7637
|
+
let rafId;
|
|
7638
|
+
let lastMousePosition = { x: 0, y: 0 };
|
|
7639
|
+
const handleGlobalMouseMove = (e) => {
|
|
7640
|
+
if (!isDragging) return;
|
|
7641
|
+
lastMousePosition = { x: e.clientX, y: e.clientY };
|
|
7642
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
7643
|
+
rafId = requestAnimationFrame(() => {
|
|
7644
|
+
const newLeft = lastMousePosition.x - dragOffset.x;
|
|
7645
|
+
const newTop = lastMousePosition.y - dragOffset.y;
|
|
7646
|
+
const rawPosition = {
|
|
7647
|
+
top: Math.max(0, Math.min(newTop, window.innerHeight - 200)),
|
|
7648
|
+
left: Math.max(0, Math.min(newLeft, window.innerWidth - 250))
|
|
7649
|
+
};
|
|
7650
|
+
updateAlignmentGuides(isDragging, rawPosition);
|
|
7651
|
+
const snappedPosition = snapToGuides(rawPosition);
|
|
7652
|
+
setActiveTooltips(
|
|
7653
|
+
(prev) => prev.map((tooltip) => {
|
|
7654
|
+
if (tooltip.id === isDragging) {
|
|
7655
|
+
return {
|
|
7656
|
+
...tooltip,
|
|
7657
|
+
position: snappedPosition
|
|
7658
|
+
};
|
|
7659
|
+
}
|
|
7660
|
+
return tooltip;
|
|
7661
|
+
})
|
|
7662
|
+
);
|
|
7663
|
+
});
|
|
7664
|
+
};
|
|
7665
|
+
const handleGlobalMouseUp = () => {
|
|
7666
|
+
if (isDragging) {
|
|
7667
|
+
setIsDragging(null);
|
|
7668
|
+
setAlignmentGuides([]);
|
|
7669
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
7670
|
+
}
|
|
7671
|
+
};
|
|
7672
|
+
if (isDragging) {
|
|
7673
|
+
document.addEventListener("mousemove", handleGlobalMouseMove, {
|
|
7674
|
+
passive: true
|
|
7675
|
+
});
|
|
7676
|
+
document.addEventListener("mouseup", handleGlobalMouseUp);
|
|
7677
|
+
document.body.style.cursor = "grabbing";
|
|
7678
|
+
document.body.style.userSelect = "none";
|
|
7679
|
+
}
|
|
7680
|
+
return () => {
|
|
7681
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
7682
|
+
document.removeEventListener("mousemove", handleGlobalMouseMove);
|
|
7683
|
+
document.removeEventListener("mouseup", handleGlobalMouseUp);
|
|
7684
|
+
document.body.style.cursor = "";
|
|
7685
|
+
document.body.style.userSelect = "";
|
|
7686
|
+
};
|
|
7687
|
+
}, [
|
|
7688
|
+
isDragging,
|
|
7689
|
+
dragOffset,
|
|
7690
|
+
alignmentGuides,
|
|
7691
|
+
updateAlignmentGuides,
|
|
7692
|
+
snapToGuides
|
|
7693
|
+
]);
|
|
7694
|
+
useEffect11(() => {
|
|
7695
|
+
const handleCloseAllTooltips = () => {
|
|
7696
|
+
setActiveTooltips([]);
|
|
7697
|
+
setGlobalTooltipCount(0);
|
|
7698
|
+
};
|
|
7699
|
+
window.addEventListener("closeAllTooltips", handleCloseAllTooltips);
|
|
7700
|
+
return () => {
|
|
7701
|
+
window.removeEventListener("closeAllTooltips", handleCloseAllTooltips);
|
|
7702
|
+
};
|
|
7703
|
+
}, []);
|
|
7704
|
+
useEffect11(() => {
|
|
7705
|
+
const handleTooltipCountRequest = () => {
|
|
7706
|
+
window.dispatchEvent(
|
|
7707
|
+
new CustomEvent("tooltipCountResponse", {
|
|
7708
|
+
detail: { count: activeTooltips.length }
|
|
7709
|
+
})
|
|
7710
|
+
);
|
|
7711
|
+
};
|
|
7712
|
+
const handleGlobalTooltipsRequest = (event) => {
|
|
7713
|
+
const { detail } = event;
|
|
7714
|
+
if (detail && detail.response && detail.requesterId) {
|
|
7715
|
+
activeTooltips.forEach((tooltip) => {
|
|
7716
|
+
if (!detail.response.find(
|
|
7717
|
+
(t) => t.id === tooltip.id
|
|
7718
|
+
)) {
|
|
7719
|
+
detail.response.push({
|
|
7720
|
+
id: tooltip.id,
|
|
7721
|
+
position: tooltip.position
|
|
7722
|
+
});
|
|
7723
|
+
}
|
|
7724
|
+
});
|
|
7725
|
+
}
|
|
7726
|
+
};
|
|
7727
|
+
window.addEventListener("requestTooltipCount", handleTooltipCountRequest);
|
|
7728
|
+
window.addEventListener(
|
|
7729
|
+
"requestGlobalTooltips",
|
|
7730
|
+
handleGlobalTooltipsRequest
|
|
7731
|
+
);
|
|
7732
|
+
return () => {
|
|
7733
|
+
window.removeEventListener(
|
|
7734
|
+
"requestTooltipCount",
|
|
7735
|
+
handleTooltipCountRequest
|
|
7736
|
+
);
|
|
7737
|
+
window.removeEventListener(
|
|
7738
|
+
"requestGlobalTooltips",
|
|
7739
|
+
handleGlobalTooltipsRequest
|
|
7740
|
+
);
|
|
7741
|
+
};
|
|
7742
|
+
}, [activeTooltips]);
|
|
7743
|
+
useEffect11(() => {
|
|
7744
|
+
if (isDragging) return;
|
|
7745
|
+
let totalCount = 0;
|
|
7746
|
+
const handleCountResponse = (event) => {
|
|
7747
|
+
const customEvent = event;
|
|
7748
|
+
totalCount += customEvent.detail.count;
|
|
7749
|
+
};
|
|
7750
|
+
window.addEventListener("tooltipCountResponse", handleCountResponse);
|
|
7751
|
+
window.dispatchEvent(new CustomEvent("requestTooltipCount"));
|
|
7752
|
+
const timeoutId = setTimeout(() => {
|
|
7753
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
7754
|
+
setGlobalTooltipCount(totalCount);
|
|
7755
|
+
}, 5);
|
|
7756
|
+
return () => {
|
|
7757
|
+
clearTimeout(timeoutId);
|
|
7758
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
7759
|
+
};
|
|
7760
|
+
}, [activeTooltips.length, isDragging]);
|
|
7761
|
+
const CustomTooltip = ({
|
|
7762
|
+
active,
|
|
7763
|
+
payload,
|
|
7764
|
+
label
|
|
7765
|
+
}) => {
|
|
7766
|
+
if (!active || !payload) return null;
|
|
7767
|
+
return /* @__PURE__ */ jsxs40("div", { className: "bg-card border border-border rounded-lg p-3 shadow-lg", children: [
|
|
7768
|
+
/* @__PURE__ */ jsx58("p", { className: "font-medium text-foreground mb-2", children: label }),
|
|
7769
|
+
payload.map(
|
|
7770
|
+
(entry, index) => /* @__PURE__ */ jsxs40("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
7771
|
+
/* @__PURE__ */ jsx58(
|
|
7772
|
+
"div",
|
|
7773
|
+
{
|
|
7774
|
+
className: "w-3 h-3 rounded-sm",
|
|
7775
|
+
style: { backgroundColor: entry.color }
|
|
7776
|
+
}
|
|
7777
|
+
),
|
|
7778
|
+
/* @__PURE__ */ jsxs40("span", { className: "text-muted-foreground", children: [
|
|
7779
|
+
entry.name,
|
|
7780
|
+
":"
|
|
7781
|
+
] }),
|
|
7782
|
+
/* @__PURE__ */ jsx58("span", { className: "text-foreground font-medium", children: entry.value?.toLocaleString("pt-BR") })
|
|
7783
|
+
] }, index)
|
|
7784
|
+
),
|
|
7785
|
+
/* @__PURE__ */ jsx58("p", { className: "text-xs text-muted-foreground mt-1", children: "Clique para fixar este tooltip" })
|
|
7786
|
+
] });
|
|
7787
|
+
};
|
|
7788
|
+
const getTitleClassName = (position) => {
|
|
7789
|
+
const baseClasses = "text-xl font-semibold text-foreground mb-3";
|
|
7790
|
+
switch (position) {
|
|
7791
|
+
case "center":
|
|
7792
|
+
return `${baseClasses} text-center`;
|
|
7793
|
+
case "right":
|
|
7794
|
+
return `${baseClasses} text-right`;
|
|
7795
|
+
default:
|
|
7796
|
+
return `${baseClasses} text-left`;
|
|
7797
|
+
}
|
|
7798
|
+
};
|
|
7799
|
+
return /* @__PURE__ */ jsxs40(
|
|
7800
|
+
"div",
|
|
7801
|
+
{
|
|
7802
|
+
className: cn("rounded-lg bg-card p-4 relative", className),
|
|
7803
|
+
style: {
|
|
7804
|
+
width: typeof width === "number" ? `${width + 32}px` : "fit-content",
|
|
7805
|
+
maxWidth: "100%"
|
|
7806
|
+
},
|
|
7807
|
+
children: [
|
|
7808
|
+
title && /* @__PURE__ */ jsx58("div", { style: { paddingLeft: `${resolvedContainerPaddingLeft}px` }, children: /* @__PURE__ */ jsx58("h3", { className: getTitleClassName(titlePosition), children: title }) }),
|
|
7809
|
+
/* @__PURE__ */ jsxs40(
|
|
7810
|
+
RechartsBarChart,
|
|
7811
|
+
{
|
|
7812
|
+
data: processedData,
|
|
7813
|
+
width: typeof width === "number" ? width : 900,
|
|
7814
|
+
height,
|
|
7815
|
+
margin: resolveChartMargins(margins, chartMargins, showLabels),
|
|
7816
|
+
onClick: handleChartClick,
|
|
7817
|
+
children: [
|
|
7818
|
+
showGrid && /* @__PURE__ */ jsx58(
|
|
7819
|
+
CartesianGrid2,
|
|
7820
|
+
{
|
|
7821
|
+
strokeDasharray: "3 3",
|
|
7822
|
+
stroke: gridColor || "hsl(var(--muted-foreground))",
|
|
7823
|
+
opacity: 0.5
|
|
7824
|
+
}
|
|
7825
|
+
),
|
|
7826
|
+
/* @__PURE__ */ jsx58(
|
|
7827
|
+
XAxis2,
|
|
7828
|
+
{
|
|
7829
|
+
dataKey: xAxisConfig.dataKey,
|
|
7830
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7831
|
+
fontSize: 12,
|
|
7832
|
+
tickLine: false,
|
|
7833
|
+
axisLine: false,
|
|
7834
|
+
tickFormatter: xAxisConfig.formatter
|
|
7835
|
+
}
|
|
7836
|
+
),
|
|
7837
|
+
/* @__PURE__ */ jsx58(
|
|
7838
|
+
YAxis2,
|
|
7839
|
+
{
|
|
7840
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7841
|
+
fontSize: 12,
|
|
7842
|
+
tickLine: false,
|
|
7843
|
+
axisLine: false,
|
|
7844
|
+
tickFormatter: (value) => value.toLocaleString("pt-BR"),
|
|
7845
|
+
domain: [0, niceMax],
|
|
7846
|
+
tickCount: 6
|
|
7847
|
+
}
|
|
7848
|
+
),
|
|
7849
|
+
showTooltip && /* @__PURE__ */ jsx58(
|
|
7850
|
+
Tooltip2,
|
|
7851
|
+
{
|
|
7852
|
+
content: /* @__PURE__ */ jsx58(CustomTooltip, {}),
|
|
7853
|
+
cursor: { fill: "hsl(var(--muted))", opacity: 0.1 }
|
|
7854
|
+
}
|
|
7855
|
+
),
|
|
7856
|
+
showLegend && /* @__PURE__ */ jsx58(
|
|
7857
|
+
Legend2,
|
|
7858
|
+
{
|
|
7859
|
+
wrapperStyle: {
|
|
7860
|
+
color: "hsl(var(--foreground))",
|
|
7861
|
+
fontSize: "14px"
|
|
7862
|
+
}
|
|
7863
|
+
}
|
|
7864
|
+
),
|
|
7865
|
+
dataKeys.map((key) => {
|
|
7866
|
+
const fieldConfig = mapperConfig[key];
|
|
7867
|
+
return /* @__PURE__ */ jsx58(
|
|
7868
|
+
Bar2,
|
|
7869
|
+
{
|
|
7870
|
+
dataKey: key,
|
|
7871
|
+
name: fieldConfig?.label || key,
|
|
7872
|
+
fill: fieldConfig?.color || finalColors[key],
|
|
7873
|
+
radius: [4, 4, 0, 0],
|
|
7874
|
+
onClick: handleBarClick,
|
|
7875
|
+
style: { cursor: "pointer" },
|
|
7876
|
+
activeBar: /* @__PURE__ */ jsx58(
|
|
7877
|
+
Rectangle2,
|
|
7878
|
+
{
|
|
7879
|
+
fill: finalColors[key],
|
|
7880
|
+
stroke: finalColors[key],
|
|
7881
|
+
strokeWidth: 2,
|
|
7882
|
+
opacity: 0.8
|
|
7883
|
+
}
|
|
7884
|
+
),
|
|
7885
|
+
children: showLabels && /* @__PURE__ */ jsx58(
|
|
7886
|
+
LabelList2,
|
|
7887
|
+
{
|
|
7888
|
+
dataKey: key,
|
|
7889
|
+
position: "top",
|
|
7890
|
+
content: pillLabelRenderer_default(
|
|
7891
|
+
finalColors[key] || "#000",
|
|
7892
|
+
"filled"
|
|
7893
|
+
)
|
|
7894
|
+
}
|
|
7895
|
+
)
|
|
7896
|
+
},
|
|
7897
|
+
key
|
|
7898
|
+
);
|
|
7899
|
+
})
|
|
7900
|
+
]
|
|
7901
|
+
}
|
|
7902
|
+
),
|
|
7903
|
+
alignmentGuides.map((guide, index) => {
|
|
7904
|
+
const isHorizontal = guide.type === "horizontal";
|
|
7905
|
+
const color = isHorizontal ? "#3b82f6" : "#ef4444";
|
|
7906
|
+
const startX = isHorizontal ? Math.min(
|
|
7907
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
7908
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
7909
|
+
) : guide.sourceTooltip.left + (isHorizontal ? 0 : guide.sourceTooltip.width / 2);
|
|
7910
|
+
const endX = isHorizontal ? Math.max(
|
|
7911
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
7912
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
7913
|
+
) : guide.targetTooltip.left + (isHorizontal ? 0 : guide.targetTooltip.width / 2);
|
|
7914
|
+
const startY = isHorizontal ? guide.sourceTooltip.top + (isHorizontal ? guide.sourceTooltip.height / 2 : 0) : Math.min(
|
|
7915
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
7916
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
7917
|
+
);
|
|
7918
|
+
const endY = isHorizontal ? guide.targetTooltip.top + (isHorizontal ? guide.targetTooltip.height / 2 : 0) : Math.max(
|
|
7919
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
7920
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
7921
|
+
);
|
|
7922
|
+
return /* @__PURE__ */ jsxs40("div", { children: [
|
|
7923
|
+
/* @__PURE__ */ jsx58(
|
|
7924
|
+
"div",
|
|
7925
|
+
{
|
|
7926
|
+
className: "fixed pointer-events-none z-30",
|
|
7927
|
+
style: {
|
|
7928
|
+
left: startX,
|
|
7929
|
+
top: startY,
|
|
7930
|
+
width: isHorizontal ? endX - startX : "2px",
|
|
7931
|
+
height: isHorizontal ? "2px" : endY - startY,
|
|
7932
|
+
backgroundColor: color,
|
|
7933
|
+
boxShadow: `0 0 8px ${color}60`,
|
|
7934
|
+
opacity: 0.9,
|
|
7935
|
+
borderStyle: "dashed",
|
|
7936
|
+
borderWidth: "1px",
|
|
7937
|
+
borderColor: color,
|
|
7938
|
+
transform: "translateZ(0)"
|
|
7939
|
+
}
|
|
7940
|
+
}
|
|
7941
|
+
),
|
|
7942
|
+
/* @__PURE__ */ jsx58(
|
|
7943
|
+
"div",
|
|
7944
|
+
{
|
|
7945
|
+
className: "fixed pointer-events-none z-31",
|
|
7946
|
+
style: {
|
|
7947
|
+
left: guide.sourceTooltip.left + guide.sourceTooltip.width / 2 - 4,
|
|
7948
|
+
top: guide.sourceTooltip.top + guide.sourceTooltip.height / 2 - 4,
|
|
7949
|
+
width: "8px",
|
|
7950
|
+
height: "8px",
|
|
7951
|
+
backgroundColor: color,
|
|
7952
|
+
borderRadius: "50%",
|
|
7953
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
7954
|
+
opacity: 0.8
|
|
7955
|
+
}
|
|
7956
|
+
}
|
|
7957
|
+
),
|
|
7958
|
+
/* @__PURE__ */ jsx58(
|
|
7959
|
+
"div",
|
|
7960
|
+
{
|
|
7961
|
+
className: "fixed pointer-events-none z-31",
|
|
7962
|
+
style: {
|
|
7963
|
+
left: guide.targetTooltip.left + guide.targetTooltip.width / 2 - 4,
|
|
7964
|
+
top: guide.targetTooltip.top + guide.targetTooltip.height / 2 - 4,
|
|
7965
|
+
width: "8px",
|
|
7966
|
+
height: "8px",
|
|
7967
|
+
backgroundColor: color,
|
|
7968
|
+
borderRadius: "50%",
|
|
7969
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
7970
|
+
opacity: 0.8
|
|
7971
|
+
}
|
|
7972
|
+
}
|
|
7973
|
+
)
|
|
7974
|
+
] }, index);
|
|
7975
|
+
}),
|
|
7976
|
+
activeTooltips.map((tooltip, index) => /* @__PURE__ */ jsx58(
|
|
7977
|
+
DraggableTooltip_default,
|
|
7978
|
+
{
|
|
7979
|
+
id: tooltip.id,
|
|
7980
|
+
data: adaptDataForTooltip(tooltip.data),
|
|
7981
|
+
position: tooltip.position,
|
|
7982
|
+
isDragging: isDragging === tooltip.id,
|
|
7983
|
+
title,
|
|
7984
|
+
dataKeys,
|
|
7985
|
+
finalColors,
|
|
7986
|
+
onMouseDown: (id, e) => handleMouseDown(e, id),
|
|
7987
|
+
onClose: (id) => {
|
|
7988
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== id));
|
|
7989
|
+
},
|
|
7990
|
+
periodLabel: "Per\xEDodo Selecionado",
|
|
7991
|
+
dataLabel: "Dados do Per\xEDodo",
|
|
7992
|
+
showCloseAllButton: index === 0,
|
|
7993
|
+
globalTooltipCount,
|
|
7994
|
+
onCloseAll: () => {
|
|
7995
|
+
window.dispatchEvent(new Event("closeAllTooltips"));
|
|
7996
|
+
},
|
|
7997
|
+
closeAllButtonPosition: "top-center",
|
|
7998
|
+
closeAllButtonVariant: "floating"
|
|
7999
|
+
},
|
|
8000
|
+
tooltip.id
|
|
8001
|
+
))
|
|
8002
|
+
]
|
|
8003
|
+
}
|
|
8004
|
+
);
|
|
8005
|
+
};
|
|
8006
|
+
var BarChart_default = BarChart;
|
|
8007
|
+
|
|
8008
|
+
// src/components/charts/LineChart.tsx
|
|
8009
|
+
import { useState as useState13, useEffect as useEffect12, useCallback as useCallback9, useMemo as useMemo8 } from "react";
|
|
8010
|
+
import {
|
|
8011
|
+
LineChart as RechartsLineChart,
|
|
8012
|
+
Line as Line2,
|
|
8013
|
+
XAxis as XAxis3,
|
|
8014
|
+
YAxis as YAxis3,
|
|
8015
|
+
CartesianGrid as CartesianGrid3,
|
|
8016
|
+
Tooltip as Tooltip3,
|
|
8017
|
+
Legend as Legend3,
|
|
8018
|
+
LabelList as LabelList3
|
|
8019
|
+
} from "recharts";
|
|
8020
|
+
import { jsx as jsx59, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
8021
|
+
var defaultData = [
|
|
8022
|
+
{ name: "A", value: 100 },
|
|
8023
|
+
{ name: "B", value: 200 },
|
|
8024
|
+
{ name: "C", value: 150 }
|
|
8025
|
+
];
|
|
8026
|
+
var DEFAULT_COLORS3 = ["#55af7d", "#8e68ff", "#2273e1"];
|
|
8027
|
+
var CustomLineChart = ({
|
|
8028
|
+
data = defaultData,
|
|
8029
|
+
className,
|
|
8030
|
+
height = 300,
|
|
8031
|
+
width = "100%",
|
|
8032
|
+
colors: colors2 = DEFAULT_COLORS3,
|
|
8033
|
+
gridColor,
|
|
8034
|
+
showGrid = true,
|
|
8035
|
+
showTooltip = true,
|
|
8036
|
+
showLegend = true,
|
|
8037
|
+
title,
|
|
8038
|
+
titlePosition = "left",
|
|
8039
|
+
strokeWidth = 2,
|
|
8040
|
+
showDots = true,
|
|
8041
|
+
showLabels = false,
|
|
8042
|
+
padding,
|
|
8043
|
+
margins,
|
|
8044
|
+
containerPaddingLeft,
|
|
8045
|
+
chartMargins
|
|
8046
|
+
}) => {
|
|
8047
|
+
const resolvedContainerPaddingLeft = resolveContainerPaddingLeft(
|
|
8048
|
+
padding,
|
|
8049
|
+
containerPaddingLeft,
|
|
8050
|
+
16
|
|
8051
|
+
);
|
|
8052
|
+
const [activeTooltips, setActiveTooltips] = useState13([]);
|
|
8053
|
+
const [isDragging, setIsDragging] = useState13(null);
|
|
8054
|
+
const [dragOffset, setDragOffset] = useState13({
|
|
8055
|
+
x: 0,
|
|
8056
|
+
y: 0
|
|
8057
|
+
});
|
|
8058
|
+
const [globalTooltipCount, setGlobalTooltipCount] = useState13(0);
|
|
8059
|
+
const [alignmentGuides, setAlignmentGuides] = useState13([]);
|
|
8060
|
+
const generateColors = (dataKeys2) => {
|
|
8061
|
+
const colorMap = {};
|
|
8062
|
+
const allColors = generateAdditionalColors(colors2, dataKeys2.length);
|
|
8063
|
+
dataKeys2.forEach((key, index) => {
|
|
8064
|
+
colorMap[key] = allColors[index] || colors2[index % colors2.length];
|
|
8065
|
+
});
|
|
8066
|
+
return colorMap;
|
|
8067
|
+
};
|
|
8068
|
+
const dataKeys = useMemo8(
|
|
8069
|
+
() => data.length > 0 ? Object.keys(data[0]).filter((key) => key !== "name") : [],
|
|
8070
|
+
[data]
|
|
8071
|
+
);
|
|
8072
|
+
const finalColors = generateColors(dataKeys);
|
|
8073
|
+
const maxDataValue = useMemo8(() => {
|
|
8074
|
+
let max = 0;
|
|
8075
|
+
for (const row of data) {
|
|
8076
|
+
const r = row;
|
|
8077
|
+
for (const key of dataKeys) {
|
|
8078
|
+
const v = r[key];
|
|
8079
|
+
if (typeof v === "number" && Number.isFinite(v) && v > max)
|
|
8080
|
+
max = v;
|
|
8081
|
+
}
|
|
8082
|
+
}
|
|
8083
|
+
return max;
|
|
8084
|
+
}, [data, dataKeys]);
|
|
8085
|
+
const niceMax = useMemo8(() => {
|
|
8086
|
+
let padding2 = 0.08;
|
|
8087
|
+
if (maxDataValue > 1e6) padding2 = 0.05;
|
|
8088
|
+
if (maxDataValue > 1e7) padding2 = 0.03;
|
|
8089
|
+
if (maxDataValue === 0) padding2 = 0.12;
|
|
8090
|
+
const padded = maxDataValue * (1 + padding2);
|
|
8091
|
+
return niceCeil(padded);
|
|
8092
|
+
}, [maxDataValue]);
|
|
8093
|
+
const ClickableDot = (props) => {
|
|
8094
|
+
const { cx, cy, payload, dataKey } = props;
|
|
8095
|
+
const handleDotClick = (e) => {
|
|
8096
|
+
e.stopPropagation();
|
|
8097
|
+
if (!payload || !cx || !cy) return;
|
|
8098
|
+
const tooltipId = `${payload.name}`;
|
|
8099
|
+
const existingIndex = activeTooltips.findIndex(
|
|
8100
|
+
(tooltip) => tooltip.id === tooltipId
|
|
8101
|
+
);
|
|
8102
|
+
if (existingIndex !== -1) {
|
|
8103
|
+
setActiveTooltips(
|
|
8104
|
+
(prev) => prev.filter((tooltip) => tooltip.id !== tooltipId)
|
|
8105
|
+
);
|
|
8106
|
+
} else {
|
|
8107
|
+
const newTooltip = {
|
|
8108
|
+
id: tooltipId,
|
|
8109
|
+
data: payload,
|
|
8110
|
+
position: {
|
|
8111
|
+
top: cy - 50,
|
|
8112
|
+
// Posição relativa ao SVG
|
|
8113
|
+
left: cx - 100
|
|
8114
|
+
}
|
|
8115
|
+
};
|
|
8116
|
+
setActiveTooltips((prev) => [...prev, newTooltip]);
|
|
8117
|
+
}
|
|
8118
|
+
};
|
|
8119
|
+
return /* @__PURE__ */ jsx59(
|
|
8120
|
+
"circle",
|
|
8121
|
+
{
|
|
8122
|
+
cx,
|
|
8123
|
+
cy,
|
|
8124
|
+
r: 6,
|
|
8125
|
+
fill: finalColors[dataKey || ""] || colors2[0],
|
|
8126
|
+
stroke: finalColors[dataKey || ""] || colors2[0],
|
|
8127
|
+
strokeWidth: 2,
|
|
8128
|
+
style: { cursor: "pointer" },
|
|
8129
|
+
onClick: handleDotClick
|
|
8130
|
+
}
|
|
8131
|
+
);
|
|
8132
|
+
};
|
|
8133
|
+
const handleChartClick = (e) => {
|
|
8134
|
+
if (e && e.activePayload && e.activePayload.length > 0) {
|
|
8135
|
+
const clickedData = e.activePayload[0].payload;
|
|
8136
|
+
const tooltipId = `${clickedData.name}`;
|
|
8137
|
+
const existingIndex = activeTooltips.findIndex(
|
|
8138
|
+
(tooltip) => tooltip.id === tooltipId
|
|
8139
|
+
);
|
|
8140
|
+
if (existingIndex !== -1) {
|
|
8141
|
+
setActiveTooltips(
|
|
8142
|
+
(prev) => prev.filter((tooltip) => tooltip.id !== tooltipId)
|
|
8143
|
+
);
|
|
8144
|
+
} else {
|
|
8145
|
+
const newTooltip = {
|
|
8146
|
+
id: tooltipId,
|
|
8147
|
+
data: clickedData,
|
|
8148
|
+
position: {
|
|
8149
|
+
top: (e.chartY || 100) - 10,
|
|
8150
|
+
left: (e.chartX || 100) - 100
|
|
8151
|
+
}
|
|
8152
|
+
};
|
|
8153
|
+
setActiveTooltips((prev) => [...prev, newTooltip]);
|
|
8154
|
+
}
|
|
8155
|
+
} else {
|
|
8156
|
+
}
|
|
8157
|
+
};
|
|
8158
|
+
const handleChartBackgroundClick = () => {
|
|
8159
|
+
setActiveTooltips([]);
|
|
8160
|
+
};
|
|
8161
|
+
const handleCloseAllTooltips = useCallback9(() => {
|
|
8162
|
+
window.dispatchEvent(new CustomEvent("closeAllTooltips"));
|
|
8163
|
+
}, []);
|
|
8164
|
+
const updateAlignmentGuides = useCallback9(
|
|
8165
|
+
(draggedTooltipId, draggedPosition) => {
|
|
8166
|
+
const SNAP_THRESHOLD = 15;
|
|
8167
|
+
const draggedTooltip = activeTooltips.find(
|
|
8168
|
+
(t) => t.id === draggedTooltipId
|
|
8169
|
+
);
|
|
8170
|
+
if (!draggedTooltip) return;
|
|
8171
|
+
const tooltipWidth = 200;
|
|
8172
|
+
const tooltipHeight = 80;
|
|
8173
|
+
const globalTooltips = [];
|
|
8174
|
+
window.dispatchEvent(
|
|
8175
|
+
new CustomEvent("requestGlobalTooltips", {
|
|
8176
|
+
detail: { requesterId: draggedTooltipId }
|
|
8177
|
+
})
|
|
8178
|
+
);
|
|
8179
|
+
activeTooltips.forEach((tooltip) => {
|
|
8180
|
+
if (tooltip.id !== draggedTooltipId) {
|
|
8181
|
+
globalTooltips.push({
|
|
8182
|
+
top: tooltip.position.top,
|
|
8183
|
+
left: tooltip.position.left,
|
|
8184
|
+
width: tooltipWidth,
|
|
8185
|
+
height: tooltipHeight,
|
|
8186
|
+
id: tooltip.id
|
|
8187
|
+
});
|
|
8188
|
+
}
|
|
8189
|
+
});
|
|
8190
|
+
const newGuides = [];
|
|
8191
|
+
globalTooltips.forEach((otherTooltip) => {
|
|
8192
|
+
const draggedCenter = {
|
|
8193
|
+
x: draggedPosition.left + tooltipWidth / 2,
|
|
8194
|
+
y: draggedPosition.top + tooltipHeight / 2
|
|
8195
|
+
};
|
|
8196
|
+
const otherCenter = {
|
|
8197
|
+
x: otherTooltip.left + otherTooltip.width / 2,
|
|
8198
|
+
y: otherTooltip.top + otherTooltip.height / 2
|
|
8199
|
+
};
|
|
8200
|
+
const horizontalDistance = Math.abs(draggedCenter.y - otherCenter.y);
|
|
8201
|
+
if (horizontalDistance <= SNAP_THRESHOLD) {
|
|
8202
|
+
newGuides.push({
|
|
8203
|
+
type: "horizontal",
|
|
8204
|
+
position: otherCenter.y,
|
|
8205
|
+
visible: true,
|
|
8206
|
+
sourceTooltip: {
|
|
8207
|
+
top: draggedPosition.top,
|
|
8208
|
+
left: draggedPosition.left,
|
|
8209
|
+
width: tooltipWidth,
|
|
8210
|
+
height: tooltipHeight
|
|
8211
|
+
},
|
|
8212
|
+
targetTooltip: {
|
|
8213
|
+
top: otherTooltip.top,
|
|
8214
|
+
left: otherTooltip.left,
|
|
8215
|
+
width: otherTooltip.width,
|
|
8216
|
+
height: otherTooltip.height
|
|
8217
|
+
}
|
|
8218
|
+
});
|
|
8219
|
+
}
|
|
8220
|
+
const verticalDistance = Math.abs(draggedCenter.x - otherCenter.x);
|
|
8221
|
+
if (verticalDistance <= SNAP_THRESHOLD) {
|
|
8222
|
+
newGuides.push({
|
|
8223
|
+
type: "vertical",
|
|
8224
|
+
position: otherCenter.x,
|
|
8225
|
+
visible: true,
|
|
8226
|
+
sourceTooltip: {
|
|
8227
|
+
top: draggedPosition.top,
|
|
8228
|
+
left: draggedPosition.left,
|
|
8229
|
+
width: tooltipWidth,
|
|
8230
|
+
height: tooltipHeight
|
|
8231
|
+
},
|
|
8232
|
+
targetTooltip: {
|
|
8233
|
+
top: otherTooltip.top,
|
|
8234
|
+
left: otherTooltip.left,
|
|
8235
|
+
width: otherTooltip.width,
|
|
8236
|
+
height: otherTooltip.height
|
|
8237
|
+
}
|
|
8238
|
+
});
|
|
8239
|
+
}
|
|
8240
|
+
});
|
|
8241
|
+
setAlignmentGuides(newGuides);
|
|
8242
|
+
},
|
|
8243
|
+
[activeTooltips]
|
|
8244
|
+
);
|
|
8245
|
+
const snapToGuides = useCallback9(
|
|
8246
|
+
(position) => {
|
|
8247
|
+
const SNAP_DISTANCE = 10;
|
|
8248
|
+
const snappedPosition = { ...position };
|
|
8249
|
+
alignmentGuides.forEach((guide) => {
|
|
8250
|
+
if (guide.type === "horizontal") {
|
|
8251
|
+
const tooltipCenter = position.top + 40;
|
|
8252
|
+
if (Math.abs(tooltipCenter - guide.position) <= SNAP_DISTANCE) {
|
|
8253
|
+
snappedPosition.top = guide.position - 40;
|
|
8254
|
+
}
|
|
8255
|
+
} else if (guide.type === "vertical") {
|
|
8256
|
+
const tooltipCenter = position.left + 100;
|
|
8257
|
+
if (Math.abs(tooltipCenter - guide.position) <= SNAP_DISTANCE) {
|
|
8258
|
+
snappedPosition.left = guide.position - 100;
|
|
8259
|
+
}
|
|
8260
|
+
}
|
|
8261
|
+
});
|
|
8262
|
+
return snappedPosition;
|
|
8263
|
+
},
|
|
8264
|
+
[alignmentGuides]
|
|
8265
|
+
);
|
|
8266
|
+
const handleMouseDown = (tooltipId, e) => {
|
|
8267
|
+
const rect = e.target.getBoundingClientRect();
|
|
8268
|
+
const offsetX = e.clientX - rect.left;
|
|
8269
|
+
const offsetY = e.clientY - rect.top;
|
|
8270
|
+
setIsDragging(tooltipId);
|
|
8271
|
+
setDragOffset({ x: offsetX, y: offsetY });
|
|
8272
|
+
};
|
|
8273
|
+
useEffect12(() => {
|
|
8274
|
+
let rafId;
|
|
8275
|
+
let lastMousePosition = { x: 0, y: 0 };
|
|
8276
|
+
const handleGlobalMouseMove = (e) => {
|
|
8277
|
+
if (!isDragging) return;
|
|
8278
|
+
lastMousePosition = { x: e.clientX, y: e.clientY };
|
|
8279
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
8280
|
+
rafId = requestAnimationFrame(() => {
|
|
8281
|
+
const newLeft = lastMousePosition.x - dragOffset.x;
|
|
8282
|
+
const newTop = lastMousePosition.y - dragOffset.y;
|
|
8283
|
+
let finalPosition = { top: newTop, left: newLeft };
|
|
8284
|
+
finalPosition = snapToGuides(finalPosition);
|
|
8285
|
+
setActiveTooltips(
|
|
8286
|
+
(prev) => prev.map(
|
|
8287
|
+
(tooltip) => tooltip.id === isDragging ? { ...tooltip, position: finalPosition } : tooltip
|
|
8288
|
+
)
|
|
8289
|
+
);
|
|
8290
|
+
updateAlignmentGuides(isDragging, finalPosition);
|
|
8291
|
+
});
|
|
8292
|
+
};
|
|
8293
|
+
const handleGlobalMouseUp = () => {
|
|
8294
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
8295
|
+
setIsDragging(null);
|
|
8296
|
+
setAlignmentGuides([]);
|
|
8297
|
+
document.body.style.cursor = "";
|
|
8298
|
+
document.body.style.userSelect = "";
|
|
8299
|
+
};
|
|
8300
|
+
if (isDragging) {
|
|
8301
|
+
document.body.style.cursor = "grabbing";
|
|
8302
|
+
document.body.style.userSelect = "none";
|
|
8303
|
+
window.addEventListener("mousemove", handleGlobalMouseMove);
|
|
8304
|
+
window.addEventListener("mouseup", handleGlobalMouseUp);
|
|
8305
|
+
}
|
|
8306
|
+
return () => {
|
|
8307
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
8308
|
+
window.removeEventListener("mousemove", handleGlobalMouseMove);
|
|
8309
|
+
window.removeEventListener("mouseup", handleGlobalMouseUp);
|
|
8310
|
+
document.body.style.cursor = "";
|
|
8311
|
+
document.body.style.userSelect = "";
|
|
8312
|
+
};
|
|
8313
|
+
}, [
|
|
8314
|
+
isDragging,
|
|
8315
|
+
dragOffset,
|
|
8316
|
+
alignmentGuides,
|
|
8317
|
+
updateAlignmentGuides,
|
|
8318
|
+
snapToGuides
|
|
8319
|
+
]);
|
|
8320
|
+
useEffect12(() => {
|
|
8321
|
+
const handleCloseAllTooltips2 = () => {
|
|
8322
|
+
setActiveTooltips([]);
|
|
8323
|
+
setGlobalTooltipCount(0);
|
|
8324
|
+
};
|
|
8325
|
+
window.addEventListener("closeAllTooltips", handleCloseAllTooltips2);
|
|
8326
|
+
return () => {
|
|
8327
|
+
window.removeEventListener("closeAllTooltips", handleCloseAllTooltips2);
|
|
8328
|
+
};
|
|
8329
|
+
}, []);
|
|
8330
|
+
useEffect12(() => {
|
|
8331
|
+
const handleTooltipCountRequest = () => {
|
|
8332
|
+
window.dispatchEvent(
|
|
8333
|
+
new CustomEvent("tooltipCountResponse", {
|
|
8334
|
+
detail: { count: activeTooltips.length }
|
|
8335
|
+
})
|
|
8336
|
+
);
|
|
8337
|
+
};
|
|
8338
|
+
const handleGlobalTooltipsRequest = (event) => {
|
|
8339
|
+
const requesterId = event.detail?.requesterId;
|
|
8340
|
+
activeTooltips.forEach((tooltip) => {
|
|
8341
|
+
if (tooltip.id !== requesterId) {
|
|
8342
|
+
window.dispatchEvent(
|
|
8343
|
+
new CustomEvent("globalTooltipResponse", {
|
|
8344
|
+
detail: {
|
|
8345
|
+
tooltip: {
|
|
8346
|
+
top: tooltip.position.top,
|
|
8347
|
+
left: tooltip.position.left,
|
|
8348
|
+
width: 200,
|
|
8349
|
+
height: 80,
|
|
8350
|
+
id: tooltip.id
|
|
8351
|
+
}
|
|
8352
|
+
}
|
|
8353
|
+
})
|
|
8354
|
+
);
|
|
8355
|
+
}
|
|
8356
|
+
});
|
|
8357
|
+
};
|
|
8358
|
+
window.addEventListener("requestTooltipCount", handleTooltipCountRequest);
|
|
8359
|
+
window.addEventListener(
|
|
8360
|
+
"requestGlobalTooltips",
|
|
8361
|
+
handleGlobalTooltipsRequest
|
|
8362
|
+
);
|
|
8363
|
+
return () => {
|
|
8364
|
+
window.removeEventListener(
|
|
8365
|
+
"requestTooltipCount",
|
|
8366
|
+
handleTooltipCountRequest
|
|
8367
|
+
);
|
|
8368
|
+
window.removeEventListener(
|
|
8369
|
+
"requestGlobalTooltips",
|
|
8370
|
+
handleGlobalTooltipsRequest
|
|
8371
|
+
);
|
|
8372
|
+
};
|
|
8373
|
+
}, [activeTooltips]);
|
|
8374
|
+
useEffect12(() => {
|
|
8375
|
+
if (isDragging) return;
|
|
8376
|
+
let totalCount = 0;
|
|
8377
|
+
const handleCountResponse = (event) => {
|
|
8378
|
+
const customEvent = event;
|
|
8379
|
+
totalCount += customEvent.detail.count;
|
|
8380
|
+
};
|
|
8381
|
+
window.addEventListener("tooltipCountResponse", handleCountResponse);
|
|
8382
|
+
window.dispatchEvent(new CustomEvent("requestTooltipCount"));
|
|
8383
|
+
const timeoutId = setTimeout(() => {
|
|
8384
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
8385
|
+
setGlobalTooltipCount(totalCount);
|
|
8386
|
+
}, 5);
|
|
8387
|
+
return () => {
|
|
8388
|
+
clearTimeout(timeoutId);
|
|
8389
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
8390
|
+
};
|
|
8391
|
+
}, [activeTooltips.length, isDragging]);
|
|
8392
|
+
const getTitleClass = () => {
|
|
8393
|
+
switch (titlePosition) {
|
|
8394
|
+
case "center":
|
|
8395
|
+
return "text-center";
|
|
8396
|
+
case "right":
|
|
8397
|
+
return "text-right";
|
|
8398
|
+
default:
|
|
8399
|
+
return "text-left";
|
|
8400
|
+
}
|
|
8401
|
+
};
|
|
8402
|
+
return /* @__PURE__ */ jsx59("div", { className: cn("relative", className), children: /* @__PURE__ */ jsxs41(
|
|
8403
|
+
"div",
|
|
8404
|
+
{
|
|
8405
|
+
className: "rounded-lg bg-card p-4 relative border border-border",
|
|
8406
|
+
style: {
|
|
8407
|
+
width: typeof width === "number" ? `${width + 32}px` : "fit-content",
|
|
8408
|
+
maxWidth: "100%"
|
|
8409
|
+
},
|
|
8410
|
+
onClick: handleChartBackgroundClick,
|
|
8411
|
+
children: [
|
|
8412
|
+
title && /* @__PURE__ */ jsx59("div", { style: { paddingLeft: `${resolvedContainerPaddingLeft}px` }, children: /* @__PURE__ */ jsx59("div", { className: cn("mb-4", getTitleClass()), children: /* @__PURE__ */ jsx59("h3", { className: "text-lg font-semibold text-foreground", children: title }) }) }),
|
|
8413
|
+
/* @__PURE__ */ jsxs41(
|
|
8414
|
+
RechartsLineChart,
|
|
8415
|
+
{
|
|
8416
|
+
data,
|
|
8417
|
+
width: typeof width === "number" ? width : 900,
|
|
8418
|
+
height,
|
|
8419
|
+
margin: resolveChartMargins(margins, chartMargins, showLabels),
|
|
8420
|
+
onClick: handleChartClick,
|
|
8421
|
+
children: [
|
|
8422
|
+
showGrid && /* @__PURE__ */ jsx59(
|
|
8423
|
+
CartesianGrid3,
|
|
8424
|
+
{
|
|
8425
|
+
strokeDasharray: "3 3",
|
|
8426
|
+
stroke: gridColor || "hsl(var(--muted-foreground))",
|
|
8427
|
+
opacity: 0.3
|
|
8428
|
+
}
|
|
8429
|
+
),
|
|
8430
|
+
/* @__PURE__ */ jsx59(
|
|
8431
|
+
XAxis3,
|
|
8432
|
+
{
|
|
8433
|
+
dataKey: "name",
|
|
8434
|
+
className: "fill-muted-foreground text-xs",
|
|
8435
|
+
fontSize: 12
|
|
8436
|
+
}
|
|
8437
|
+
),
|
|
8438
|
+
/* @__PURE__ */ jsx59(
|
|
8439
|
+
YAxis3,
|
|
8440
|
+
{
|
|
8441
|
+
className: "fill-muted-foreground text-xs",
|
|
8442
|
+
fontSize: 12,
|
|
8443
|
+
tickFormatter: (value) => compactTick(Number(value)),
|
|
8444
|
+
domain: [0, niceMax],
|
|
8445
|
+
tickCount: 6
|
|
8446
|
+
}
|
|
8447
|
+
),
|
|
8448
|
+
showTooltip && /* @__PURE__ */ jsx59(Tooltip3, { content: () => null }),
|
|
8449
|
+
showLegend && /* @__PURE__ */ jsx59(
|
|
8450
|
+
Legend3,
|
|
8451
|
+
{
|
|
8452
|
+
wrapperStyle: {
|
|
8453
|
+
fontSize: "12px",
|
|
8454
|
+
color: "hsl(var(--muted-foreground))"
|
|
8455
|
+
}
|
|
8456
|
+
}
|
|
8457
|
+
),
|
|
8458
|
+
dataKeys.map((key) => /* @__PURE__ */ jsx59(
|
|
8459
|
+
Line2,
|
|
8460
|
+
{
|
|
8461
|
+
type: "monotone",
|
|
8462
|
+
dataKey: key,
|
|
8463
|
+
stroke: finalColors[key],
|
|
8464
|
+
strokeWidth,
|
|
8465
|
+
dot: showDots ? { r: 4, cursor: "pointer" } : false,
|
|
8466
|
+
activeDot: (props) => /* @__PURE__ */ jsx59(ClickableDot, { ...props, dataKey: key }),
|
|
8467
|
+
children: showLabels && /* @__PURE__ */ jsx59(
|
|
8468
|
+
LabelList3,
|
|
8469
|
+
{
|
|
8470
|
+
dataKey: key,
|
|
8471
|
+
position: "top",
|
|
8472
|
+
content: pillLabelRenderer_default(
|
|
8473
|
+
finalColors[key] || "#000",
|
|
8474
|
+
"filled"
|
|
8475
|
+
),
|
|
8476
|
+
offset: 14
|
|
8477
|
+
}
|
|
8478
|
+
)
|
|
8479
|
+
},
|
|
8480
|
+
key
|
|
8481
|
+
))
|
|
8482
|
+
]
|
|
8483
|
+
}
|
|
8484
|
+
),
|
|
8485
|
+
alignmentGuides.map((guide, index) => {
|
|
8486
|
+
const isHorizontal = guide.type === "horizontal";
|
|
8487
|
+
const color = isHorizontal ? "#3b82f6" : "#ef4444";
|
|
8488
|
+
const startX = isHorizontal ? Math.min(
|
|
8489
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
8490
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
8491
|
+
) : guide.sourceTooltip.left + (isHorizontal ? 0 : guide.sourceTooltip.width / 2);
|
|
8492
|
+
const endX = isHorizontal ? Math.max(
|
|
8493
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
8494
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
8495
|
+
) : guide.targetTooltip.left + (isHorizontal ? 0 : guide.targetTooltip.width / 2);
|
|
8496
|
+
const startY = isHorizontal ? guide.sourceTooltip.top + (isHorizontal ? guide.sourceTooltip.height / 2 : 0) : Math.min(
|
|
8497
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
8498
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
8499
|
+
);
|
|
8500
|
+
const endY = isHorizontal ? guide.targetTooltip.top + (isHorizontal ? guide.targetTooltip.height / 2 : 0) : Math.max(
|
|
8501
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
8502
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
8503
|
+
);
|
|
8504
|
+
return /* @__PURE__ */ jsxs41("div", { children: [
|
|
8505
|
+
/* @__PURE__ */ jsx59(
|
|
8506
|
+
"div",
|
|
8507
|
+
{
|
|
8508
|
+
className: "fixed pointer-events-none z-30",
|
|
8509
|
+
style: {
|
|
8510
|
+
left: startX,
|
|
8511
|
+
top: startY,
|
|
8512
|
+
width: isHorizontal ? endX - startX : "2px",
|
|
8513
|
+
height: isHorizontal ? "2px" : endY - startY,
|
|
8514
|
+
backgroundColor: color,
|
|
8515
|
+
boxShadow: `0 0 8px ${color}60`,
|
|
8516
|
+
opacity: 0.9,
|
|
8517
|
+
borderStyle: "dashed",
|
|
8518
|
+
borderWidth: "1px",
|
|
8519
|
+
borderColor: color,
|
|
8520
|
+
transform: "translateZ(0)"
|
|
8521
|
+
}
|
|
8522
|
+
}
|
|
8523
|
+
),
|
|
8524
|
+
/* @__PURE__ */ jsx59(
|
|
8525
|
+
"div",
|
|
8526
|
+
{
|
|
8527
|
+
className: "fixed pointer-events-none z-31",
|
|
8528
|
+
style: {
|
|
8529
|
+
left: guide.sourceTooltip.left + guide.sourceTooltip.width / 2 - 4,
|
|
8530
|
+
top: guide.sourceTooltip.top + guide.sourceTooltip.height / 2 - 4,
|
|
8531
|
+
width: "8px",
|
|
8532
|
+
height: "8px",
|
|
8533
|
+
backgroundColor: color,
|
|
8534
|
+
borderRadius: "50%",
|
|
8535
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
8536
|
+
opacity: 0.8
|
|
8537
|
+
}
|
|
8538
|
+
}
|
|
8539
|
+
),
|
|
8540
|
+
/* @__PURE__ */ jsx59(
|
|
8541
|
+
"div",
|
|
8542
|
+
{
|
|
8543
|
+
className: "fixed pointer-events-none z-31",
|
|
8544
|
+
style: {
|
|
8545
|
+
left: guide.targetTooltip.left + guide.targetTooltip.width / 2 - 4,
|
|
8546
|
+
top: guide.targetTooltip.top + guide.targetTooltip.height / 2 - 4,
|
|
8547
|
+
width: "8px",
|
|
8548
|
+
height: "8px",
|
|
8549
|
+
backgroundColor: color,
|
|
8550
|
+
borderRadius: "50%",
|
|
8551
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
8552
|
+
opacity: 0.8
|
|
8553
|
+
}
|
|
8554
|
+
}
|
|
8555
|
+
)
|
|
8556
|
+
] }, index);
|
|
8557
|
+
}),
|
|
8558
|
+
activeTooltips.map((tooltip, index) => /* @__PURE__ */ jsx59(
|
|
8559
|
+
DraggableTooltip_default,
|
|
8560
|
+
{
|
|
8561
|
+
id: tooltip.id,
|
|
8562
|
+
data: tooltip.data,
|
|
8563
|
+
position: tooltip.position,
|
|
8564
|
+
isDragging: isDragging === tooltip.id,
|
|
8565
|
+
title,
|
|
8566
|
+
dataKeys,
|
|
8567
|
+
finalColors,
|
|
8568
|
+
onMouseDown: (id, e) => handleMouseDown(id, e),
|
|
8569
|
+
onClose: (id) => {
|
|
8570
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== id));
|
|
8571
|
+
},
|
|
8572
|
+
periodLabel: "Ponto Selecionado",
|
|
8573
|
+
dataLabel: "Dados do Ponto",
|
|
8574
|
+
showCloseAllButton: index === 0,
|
|
8575
|
+
globalTooltipCount,
|
|
8576
|
+
onCloseAll: handleCloseAllTooltips,
|
|
8577
|
+
closeAllButtonPosition: "top-center",
|
|
8578
|
+
closeAllButtonVariant: "floating"
|
|
8579
|
+
},
|
|
8580
|
+
tooltip.id
|
|
8581
|
+
))
|
|
8582
|
+
]
|
|
8583
|
+
}
|
|
8584
|
+
) });
|
|
8585
|
+
};
|
|
8586
|
+
var LineChart_default = CustomLineChart;
|
|
8587
|
+
|
|
8588
|
+
// src/components/charts/PieChart.tsx
|
|
8589
|
+
import {
|
|
8590
|
+
PieChart as RechartsPieChart,
|
|
8591
|
+
Pie,
|
|
8592
|
+
Cell,
|
|
8593
|
+
ResponsiveContainer as ResponsiveContainer2,
|
|
8594
|
+
Tooltip as Tooltip4,
|
|
8595
|
+
Legend as Legend4
|
|
8596
|
+
} from "recharts";
|
|
8597
|
+
import { jsx as jsx60, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
8598
|
+
var defaultData2 = [
|
|
8599
|
+
{ name: "Vendas", value: 4e3 },
|
|
8600
|
+
{ name: "Marketing", value: 3e3 },
|
|
8601
|
+
{ name: "Desenvolvimento", value: 2e3 },
|
|
8602
|
+
{ name: "Suporte", value: 1e3 },
|
|
8603
|
+
{ name: "Outros", value: 800 }
|
|
8604
|
+
];
|
|
8605
|
+
var DEFAULT_COLORS4 = [
|
|
8606
|
+
"#55af7d",
|
|
8607
|
+
// verde do projeto
|
|
8608
|
+
"#8e68ff",
|
|
8609
|
+
// roxo do projeto
|
|
8610
|
+
"#2273e1",
|
|
8611
|
+
// azul do projeto
|
|
8612
|
+
"#f59e0b",
|
|
8613
|
+
// amarelo complementar
|
|
8614
|
+
"#ef4444",
|
|
8615
|
+
// vermelho complementar
|
|
8616
|
+
"#8b5cf6",
|
|
8617
|
+
// roxo claro
|
|
8618
|
+
"#06b6d4",
|
|
8619
|
+
// ciano
|
|
8620
|
+
"#84cc16"
|
|
8621
|
+
// verde lima
|
|
8622
|
+
];
|
|
8623
|
+
var RADIAN = Math.PI / 180;
|
|
8624
|
+
var renderCustomizedLabel = ({
|
|
8625
|
+
cx = 0,
|
|
8626
|
+
cy = 0,
|
|
8627
|
+
midAngle = 0,
|
|
8628
|
+
innerRadius = 0,
|
|
8629
|
+
outerRadius = 0,
|
|
8630
|
+
percent = 0
|
|
8631
|
+
}) => {
|
|
8632
|
+
const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
|
|
8633
|
+
const x = cx + radius * Math.cos(-midAngle * RADIAN);
|
|
8634
|
+
const y = cy + radius * Math.sin(-midAngle * RADIAN);
|
|
8635
|
+
return /* @__PURE__ */ jsx60(
|
|
8636
|
+
"text",
|
|
8637
|
+
{
|
|
8638
|
+
x,
|
|
8639
|
+
y,
|
|
8640
|
+
fill: "white",
|
|
8641
|
+
textAnchor: x > cx ? "start" : "end",
|
|
8642
|
+
dominantBaseline: "central",
|
|
8643
|
+
fontSize: 12,
|
|
8644
|
+
fontWeight: "600",
|
|
8645
|
+
children: `${(percent * 100).toFixed(0)}%`
|
|
8646
|
+
}
|
|
8647
|
+
);
|
|
8648
|
+
};
|
|
8649
|
+
var CustomPieChart = ({
|
|
8650
|
+
data = defaultData2,
|
|
8651
|
+
className,
|
|
8652
|
+
height = 400,
|
|
8653
|
+
width = "100%",
|
|
8654
|
+
colors: colors2,
|
|
8655
|
+
showTooltip = true,
|
|
8656
|
+
showLegend = true,
|
|
8657
|
+
showLabels = true,
|
|
8658
|
+
innerRadius = 0,
|
|
8659
|
+
outerRadius = 120,
|
|
8660
|
+
centerX = "50%",
|
|
8661
|
+
centerY = "50%"
|
|
8662
|
+
}) => {
|
|
8663
|
+
const finalColors = colors2 || DEFAULT_COLORS4;
|
|
8664
|
+
return /* @__PURE__ */ jsx60("div", { className: cn("w-full rounded-lg bg-card p-4", className), children: /* @__PURE__ */ jsx60(ResponsiveContainer2, { width, height, children: /* @__PURE__ */ jsxs42(RechartsPieChart, { children: [
|
|
8665
|
+
/* @__PURE__ */ jsx60(
|
|
8666
|
+
Pie,
|
|
8667
|
+
{
|
|
8668
|
+
data,
|
|
8669
|
+
cx: centerX,
|
|
8670
|
+
cy: centerY,
|
|
8671
|
+
labelLine: false,
|
|
8672
|
+
label: showLabels ? renderCustomizedLabel : false,
|
|
8673
|
+
outerRadius,
|
|
8674
|
+
innerRadius,
|
|
8675
|
+
fill: "#8884d8",
|
|
8676
|
+
dataKey: "value",
|
|
8677
|
+
children: data.map((entry, index) => /* @__PURE__ */ jsx60(
|
|
8678
|
+
Cell,
|
|
8679
|
+
{
|
|
8680
|
+
fill: finalColors[index % finalColors.length]
|
|
8681
|
+
},
|
|
8682
|
+
`cell-${entry.name}-${index}`
|
|
8683
|
+
))
|
|
8684
|
+
}
|
|
8685
|
+
),
|
|
8686
|
+
showTooltip && /* @__PURE__ */ jsx60(
|
|
8687
|
+
Tooltip4,
|
|
8688
|
+
{
|
|
8689
|
+
contentStyle: {
|
|
8690
|
+
backgroundColor: "hsl(var(--popover))",
|
|
8691
|
+
border: "1px solid hsl(var(--border))",
|
|
8692
|
+
borderRadius: "6px",
|
|
8693
|
+
color: "hsl(var(--popover-foreground))"
|
|
8694
|
+
}
|
|
8695
|
+
}
|
|
8696
|
+
),
|
|
8697
|
+
showLegend && /* @__PURE__ */ jsx60(Legend4, {})
|
|
8698
|
+
] }) }) });
|
|
8699
|
+
};
|
|
8700
|
+
var PieChart_default = CustomPieChart;
|
|
8701
|
+
|
|
8702
|
+
// src/components/charts/hooks/useChartHighlights.tsx
|
|
8703
|
+
import { useState as useState14, useCallback as useCallback10 } from "react";
|
|
8704
|
+
var useChartHighlights = () => {
|
|
8705
|
+
const [highlightedSeries, setHighlightedSeries] = useState14(
|
|
8706
|
+
/* @__PURE__ */ new Set()
|
|
8707
|
+
);
|
|
8708
|
+
const [showOnlyHighlighted, setShowOnlyHighlighted] = useState14(false);
|
|
8709
|
+
const toggleHighlight = useCallback10((key) => {
|
|
8710
|
+
setHighlightedSeries((prev) => {
|
|
8711
|
+
const next = new Set(prev);
|
|
8712
|
+
if (next.has(key)) {
|
|
8713
|
+
next.delete(key);
|
|
8714
|
+
} else {
|
|
8715
|
+
next.add(key);
|
|
8716
|
+
}
|
|
8717
|
+
return next;
|
|
8718
|
+
});
|
|
8719
|
+
}, []);
|
|
8720
|
+
const clearHighlights = useCallback10(() => {
|
|
8721
|
+
setHighlightedSeries(/* @__PURE__ */ new Set());
|
|
8722
|
+
setShowOnlyHighlighted(false);
|
|
8723
|
+
}, []);
|
|
8724
|
+
const isHighlighted = useCallback10(
|
|
8725
|
+
(key) => {
|
|
8726
|
+
return highlightedSeries.has(key);
|
|
8727
|
+
},
|
|
8728
|
+
[highlightedSeries]
|
|
8729
|
+
);
|
|
8730
|
+
const getSeriesStyle = useCallback10(
|
|
8731
|
+
(key) => {
|
|
8732
|
+
const hasHighlights = highlightedSeries.size > 0;
|
|
8733
|
+
const isSeriesHighlighted = highlightedSeries.has(key);
|
|
8734
|
+
if (showOnlyHighlighted && !isSeriesHighlighted) {
|
|
8735
|
+
return {
|
|
8736
|
+
opacity: 0,
|
|
8737
|
+
pointerEvents: "none",
|
|
8738
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8739
|
+
};
|
|
8740
|
+
}
|
|
8741
|
+
if (!hasHighlights) {
|
|
8742
|
+
return {
|
|
8743
|
+
opacity: 1,
|
|
8744
|
+
transform: "scale(1)",
|
|
8745
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8746
|
+
};
|
|
8747
|
+
}
|
|
8748
|
+
if (isSeriesHighlighted) {
|
|
8749
|
+
return {
|
|
8750
|
+
opacity: 1,
|
|
8751
|
+
transform: "scale(1.02)",
|
|
8752
|
+
filter: "drop-shadow(0 4px 12px rgba(0, 0, 0, 0.15))",
|
|
8753
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8754
|
+
};
|
|
8755
|
+
}
|
|
8756
|
+
return {
|
|
8757
|
+
opacity: 0.25,
|
|
8758
|
+
transform: "scale(0.98)",
|
|
8759
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8760
|
+
};
|
|
8761
|
+
},
|
|
8762
|
+
[highlightedSeries, showOnlyHighlighted]
|
|
8763
|
+
);
|
|
8764
|
+
return {
|
|
8765
|
+
highlightedSeries,
|
|
8766
|
+
showOnlyHighlighted,
|
|
8767
|
+
toggleHighlight,
|
|
8768
|
+
setShowOnlyHighlighted,
|
|
8769
|
+
clearHighlights,
|
|
8770
|
+
getSeriesStyle,
|
|
8771
|
+
isHighlighted
|
|
8772
|
+
};
|
|
8773
|
+
};
|
|
8774
|
+
|
|
8775
|
+
// src/hooks/use-drag.tsx
|
|
8776
|
+
import { useState as useState15, useCallback as useCallback11, useRef as useRef5, useEffect as useEffect13 } from "react";
|
|
8777
|
+
var useDrag = (options = {}) => {
|
|
8778
|
+
const [isDragging, setIsDragging] = useState15(null);
|
|
8779
|
+
const [positions, setPositions] = useState15({});
|
|
8780
|
+
const dragStartPos = useRef5(null);
|
|
8781
|
+
const dragId = useRef5(null);
|
|
8782
|
+
const handleMouseDown = useCallback11((id, e) => {
|
|
8783
|
+
e.preventDefault();
|
|
8784
|
+
const currentPosition = positions[id] || { top: 0, left: 0 };
|
|
8785
|
+
dragStartPos.current = {
|
|
8786
|
+
x: e.clientX,
|
|
8787
|
+
y: e.clientY,
|
|
8788
|
+
elementX: currentPosition.left,
|
|
8789
|
+
elementY: currentPosition.top
|
|
8790
|
+
};
|
|
8791
|
+
dragId.current = id;
|
|
8792
|
+
setIsDragging(id);
|
|
8793
|
+
options.onDragStart?.(id);
|
|
8794
|
+
}, [positions, options]);
|
|
8795
|
+
const handleMouseMove = useCallback11((e) => {
|
|
8796
|
+
if (!isDragging || !dragStartPos.current || !dragId.current) return;
|
|
8797
|
+
const deltaX = e.clientX - dragStartPos.current.x;
|
|
8798
|
+
const deltaY = e.clientY - dragStartPos.current.y;
|
|
8799
|
+
const newPosition = {
|
|
8800
|
+
left: dragStartPos.current.elementX + deltaX,
|
|
8801
|
+
top: dragStartPos.current.elementY + deltaY
|
|
8802
|
+
};
|
|
8803
|
+
newPosition.left = Math.max(0, Math.min(window.innerWidth - 300, newPosition.left));
|
|
8804
|
+
newPosition.top = Math.max(0, Math.min(window.innerHeight - 200, newPosition.top));
|
|
8805
|
+
setPositions((prev) => ({
|
|
8806
|
+
...prev,
|
|
8807
|
+
[dragId.current]: newPosition
|
|
8808
|
+
}));
|
|
8809
|
+
options.onDrag?.(dragId.current, newPosition);
|
|
8810
|
+
}, [isDragging, options]);
|
|
8811
|
+
const handleMouseUp = useCallback11(() => {
|
|
8812
|
+
if (dragId.current) {
|
|
8813
|
+
options.onDragEnd?.(dragId.current);
|
|
8814
|
+
}
|
|
8815
|
+
setIsDragging(null);
|
|
8816
|
+
dragStartPos.current = null;
|
|
8817
|
+
dragId.current = null;
|
|
8818
|
+
}, [options]);
|
|
8819
|
+
useEffect13(() => {
|
|
6678
8820
|
if (isDragging) {
|
|
6679
8821
|
document.addEventListener("mousemove", handleMouseMove);
|
|
6680
8822
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -6686,16 +8828,16 @@ var useDrag = (options = {}) => {
|
|
|
6686
8828
|
};
|
|
6687
8829
|
}
|
|
6688
8830
|
}, [isDragging, handleMouseMove, handleMouseUp]);
|
|
6689
|
-
const setPosition =
|
|
8831
|
+
const setPosition = useCallback11((id, position) => {
|
|
6690
8832
|
setPositions((prev) => ({
|
|
6691
8833
|
...prev,
|
|
6692
8834
|
[id]: position
|
|
6693
8835
|
}));
|
|
6694
8836
|
}, []);
|
|
6695
|
-
const getPosition =
|
|
8837
|
+
const getPosition = useCallback11((id) => {
|
|
6696
8838
|
return positions[id] || { top: 0, left: 0 };
|
|
6697
8839
|
}, [positions]);
|
|
6698
|
-
const isElementDragging =
|
|
8840
|
+
const isElementDragging = useCallback11((id) => {
|
|
6699
8841
|
return isDragging === id;
|
|
6700
8842
|
}, [isDragging]);
|
|
6701
8843
|
return {
|
|
@@ -6722,6 +8864,7 @@ export {
|
|
|
6722
8864
|
AvatarFallbackBase,
|
|
6723
8865
|
AvatarImageBase,
|
|
6724
8866
|
BadgeBase,
|
|
8867
|
+
BarChart_default as BarChart,
|
|
6725
8868
|
BreadcrumbBase,
|
|
6726
8869
|
BreadcrumbEllipsisBase,
|
|
6727
8870
|
BreadcrumbItemBase,
|
|
@@ -6743,6 +8886,7 @@ export {
|
|
|
6743
8886
|
CarouselItemBase,
|
|
6744
8887
|
CarouselNextBase,
|
|
6745
8888
|
CarouselPrevious,
|
|
8889
|
+
Chart_default as Chart,
|
|
6746
8890
|
CheckboxBase,
|
|
6747
8891
|
CloseAllButton_default as CloseAllButton,
|
|
6748
8892
|
CollapsibleBase,
|
|
@@ -6821,6 +8965,7 @@ export {
|
|
|
6821
8965
|
InputOTPSeparatorBase,
|
|
6822
8966
|
InputOTPSlotBase,
|
|
6823
8967
|
LabelBase_default as LabelBase,
|
|
8968
|
+
LineChart_default as LineChart,
|
|
6824
8969
|
LoadingBase,
|
|
6825
8970
|
ModeToggleBase,
|
|
6826
8971
|
MultiCombobox,
|
|
@@ -6833,6 +8978,7 @@ export {
|
|
|
6833
8978
|
NavigationMenuTriggerBase,
|
|
6834
8979
|
NavigationMenuViewportBase,
|
|
6835
8980
|
PeriodsDropdown_default as PeriodsDropdown,
|
|
8981
|
+
PieChart_default as PieChart,
|
|
6836
8982
|
PopoverAnchorBase,
|
|
6837
8983
|
PopoverBase,
|
|
6838
8984
|
PopoverContentBase,
|
|
@@ -6928,6 +9074,7 @@ export {
|
|
|
6928
9074
|
resolveChartMargins,
|
|
6929
9075
|
resolveContainerPaddingLeft,
|
|
6930
9076
|
toast,
|
|
9077
|
+
useChartHighlights,
|
|
6931
9078
|
useDrag,
|
|
6932
9079
|
useIsMobile,
|
|
6933
9080
|
useTheme
|