@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.js
CHANGED
|
@@ -500,6 +500,7 @@ __export(index_exports, {
|
|
|
500
500
|
AvatarFallbackBase: () => AvatarFallbackBase,
|
|
501
501
|
AvatarImageBase: () => AvatarImageBase,
|
|
502
502
|
BadgeBase: () => BadgeBase,
|
|
503
|
+
BarChart: () => BarChart_default,
|
|
503
504
|
BreadcrumbBase: () => BreadcrumbBase,
|
|
504
505
|
BreadcrumbEllipsisBase: () => BreadcrumbEllipsisBase,
|
|
505
506
|
BreadcrumbItemBase: () => BreadcrumbItemBase,
|
|
@@ -521,6 +522,7 @@ __export(index_exports, {
|
|
|
521
522
|
CarouselItemBase: () => CarouselItemBase,
|
|
522
523
|
CarouselNextBase: () => CarouselNextBase,
|
|
523
524
|
CarouselPrevious: () => CarouselPrevious,
|
|
525
|
+
Chart: () => Chart_default,
|
|
524
526
|
CheckboxBase: () => CheckboxBase,
|
|
525
527
|
CloseAllButton: () => CloseAllButton_default,
|
|
526
528
|
CollapsibleBase: () => CollapsibleBase,
|
|
@@ -599,6 +601,7 @@ __export(index_exports, {
|
|
|
599
601
|
InputOTPSeparatorBase: () => InputOTPSeparatorBase,
|
|
600
602
|
InputOTPSlotBase: () => InputOTPSlotBase,
|
|
601
603
|
LabelBase: () => LabelBase_default,
|
|
604
|
+
LineChart: () => LineChart_default,
|
|
602
605
|
LoadingBase: () => LoadingBase,
|
|
603
606
|
ModeToggleBase: () => ModeToggleBase,
|
|
604
607
|
MultiCombobox: () => MultiCombobox,
|
|
@@ -611,6 +614,7 @@ __export(index_exports, {
|
|
|
611
614
|
NavigationMenuTriggerBase: () => NavigationMenuTriggerBase,
|
|
612
615
|
NavigationMenuViewportBase: () => NavigationMenuViewportBase,
|
|
613
616
|
PeriodsDropdown: () => PeriodsDropdown_default,
|
|
617
|
+
PieChart: () => PieChart_default,
|
|
614
618
|
PopoverAnchorBase: () => PopoverAnchorBase,
|
|
615
619
|
PopoverBase: () => PopoverBase,
|
|
616
620
|
PopoverContentBase: () => PopoverContentBase,
|
|
@@ -706,6 +710,7 @@ __export(index_exports, {
|
|
|
706
710
|
resolveChartMargins: () => resolveChartMargins,
|
|
707
711
|
resolveContainerPaddingLeft: () => resolveContainerPaddingLeft,
|
|
708
712
|
toast: () => toast,
|
|
713
|
+
useChartHighlights: () => useChartHighlights,
|
|
709
714
|
useDrag: () => useDrag,
|
|
710
715
|
useIsMobile: () => useIsMobile,
|
|
711
716
|
useTheme: () => useTheme
|
|
@@ -4623,43 +4628,119 @@ function ModeToggleBase({
|
|
|
4623
4628
|
] });
|
|
4624
4629
|
}
|
|
4625
4630
|
|
|
4631
|
+
// src/components/ui/DestructiveDialog.tsx
|
|
4632
|
+
var React29 = __toESM(require("react"));
|
|
4633
|
+
var import_react25 = require("@phosphor-icons/react");
|
|
4634
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
4635
|
+
var DestructiveDialog = ({
|
|
4636
|
+
title,
|
|
4637
|
+
description,
|
|
4638
|
+
onConfirm,
|
|
4639
|
+
onCancel,
|
|
4640
|
+
children,
|
|
4641
|
+
triggerContent
|
|
4642
|
+
}) => {
|
|
4643
|
+
const titleId = "destructive-dialog-title";
|
|
4644
|
+
const descriptionId = "destructive-dialog-description";
|
|
4645
|
+
const triggerEl = React29.isValidElement(children) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AlertDialogTriggerBase, { asChild: true, children }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AlertDialogTriggerBase, { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ButtonBase, { variant: "destructive", children: triggerContent ?? "Excluir" }) });
|
|
4646
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(AlertDialogBase, { children: [
|
|
4647
|
+
triggerEl,
|
|
4648
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
4649
|
+
AlertDialogContentBase,
|
|
4650
|
+
{
|
|
4651
|
+
role: "alertdialog",
|
|
4652
|
+
"aria-modal": "true",
|
|
4653
|
+
"aria-labelledby": titleId,
|
|
4654
|
+
"aria-describedby": descriptionId,
|
|
4655
|
+
className: cn("border border-destructive bg-background"),
|
|
4656
|
+
children: [
|
|
4657
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-start gap-4", children: [
|
|
4658
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex items-center justify-center w-10 h-10 rounded-full ring-1 ring-destructive/30", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react25.XCircleIcon, { className: "w-6 h-6 text-destructive" }) }),
|
|
4659
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex-1", children: [
|
|
4660
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
4661
|
+
AlertDialogTitleBase,
|
|
4662
|
+
{
|
|
4663
|
+
id: titleId,
|
|
4664
|
+
className: "text-lg sm:text-xl font-semibold text-destructive",
|
|
4665
|
+
children: title
|
|
4666
|
+
}
|
|
4667
|
+
),
|
|
4668
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
4669
|
+
AlertDialogDescriptionBase,
|
|
4670
|
+
{
|
|
4671
|
+
id: descriptionId,
|
|
4672
|
+
className: "mt-2 text-sm text-muted-foreground",
|
|
4673
|
+
children: description
|
|
4674
|
+
}
|
|
4675
|
+
)
|
|
4676
|
+
] })
|
|
4677
|
+
] }),
|
|
4678
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(AlertDialogFooterBase, { className: "mt-2 flex justify-end gap-3", children: [
|
|
4679
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
4680
|
+
AlertDialogCancelBase,
|
|
4681
|
+
{
|
|
4682
|
+
onClick: onCancel,
|
|
4683
|
+
className: cn(
|
|
4684
|
+
buttonVariantsBase({ variant: "outline", size: "default" }),
|
|
4685
|
+
"hover:bg-foreground/5 hover:text-primary hover:opacity-90 hover:shadow-none"
|
|
4686
|
+
),
|
|
4687
|
+
children: "Cancelar"
|
|
4688
|
+
}
|
|
4689
|
+
),
|
|
4690
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
4691
|
+
AlertDialogActionBase,
|
|
4692
|
+
{
|
|
4693
|
+
onClick: onConfirm,
|
|
4694
|
+
className: cn(
|
|
4695
|
+
buttonVariantsBase({ variant: "destructive", size: "default" })
|
|
4696
|
+
),
|
|
4697
|
+
children: "Confirmar"
|
|
4698
|
+
}
|
|
4699
|
+
)
|
|
4700
|
+
] })
|
|
4701
|
+
]
|
|
4702
|
+
}
|
|
4703
|
+
)
|
|
4704
|
+
] });
|
|
4705
|
+
};
|
|
4706
|
+
|
|
4626
4707
|
// src/components/date-time-picker/DateTimePicker.tsx
|
|
4627
4708
|
var import_date_fns = require("date-fns");
|
|
4628
4709
|
|
|
4629
4710
|
// src/components/date-time-picker/calendar.tsx
|
|
4630
|
-
var
|
|
4711
|
+
var React30 = __toESM(require("react"));
|
|
4631
4712
|
var import_react_day_picker2 = require("react-day-picker");
|
|
4632
|
-
var
|
|
4713
|
+
var import_react26 = require("@phosphor-icons/react");
|
|
4633
4714
|
var import_framer_motion6 = require("framer-motion");
|
|
4634
|
-
var
|
|
4715
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
4635
4716
|
function CalendarBase2({
|
|
4636
4717
|
className,
|
|
4637
4718
|
classNames,
|
|
4638
4719
|
showOutsideDays = true,
|
|
4639
4720
|
...props
|
|
4640
4721
|
}) {
|
|
4641
|
-
const [month, setMonth] =
|
|
4722
|
+
const [month, setMonth] = React30.useState(
|
|
4642
4723
|
props.month || props.defaultMonth || /* @__PURE__ */ new Date()
|
|
4643
4724
|
);
|
|
4644
|
-
const [direction, setDirection] =
|
|
4725
|
+
const [direction, setDirection] = React30.useState(1);
|
|
4645
4726
|
const handleMonthChange = (newMonth) => {
|
|
4646
4727
|
const isNext = newMonth > month ? 1 : -1;
|
|
4647
4728
|
setDirection(isNext);
|
|
4648
4729
|
setMonth(newMonth);
|
|
4649
4730
|
props.onMonthChange?.(newMonth);
|
|
4650
4731
|
};
|
|
4651
|
-
return /* @__PURE__ */ (0,
|
|
4732
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
4652
4733
|
"div",
|
|
4653
4734
|
{
|
|
4654
4735
|
className: cn(
|
|
4655
4736
|
"rounded-2xl border bg-background p-4 shadow-lg overflow-hidden w-full h-full flex flex-col",
|
|
4656
4737
|
className
|
|
4657
4738
|
),
|
|
4658
|
-
children: /* @__PURE__ */ (0,
|
|
4739
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "relative flex-1 flex flex-col min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_framer_motion6.AnimatePresence, { initial: false, mode: "wait", custom: direction, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
4659
4740
|
"div",
|
|
4660
4741
|
{
|
|
4661
4742
|
className: "w-full h-full flex flex-col",
|
|
4662
|
-
children: /* @__PURE__ */ (0,
|
|
4743
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
4663
4744
|
import_react_day_picker2.DayPicker,
|
|
4664
4745
|
{
|
|
4665
4746
|
showOutsideDays,
|
|
@@ -4708,8 +4789,8 @@ function CalendarBase2({
|
|
|
4708
4789
|
...classNames
|
|
4709
4790
|
},
|
|
4710
4791
|
components: {
|
|
4711
|
-
IconLeft: () => /* @__PURE__ */ (0,
|
|
4712
|
-
IconRight: () => /* @__PURE__ */ (0,
|
|
4792
|
+
IconLeft: () => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react26.CaretLeftIcon, { className: "h-4 w-4" }),
|
|
4793
|
+
IconRight: () => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react26.CaretRightIcon, { className: "h-4 w-4" })
|
|
4713
4794
|
},
|
|
4714
4795
|
...props
|
|
4715
4796
|
}
|
|
@@ -4724,15 +4805,15 @@ CalendarBase2.displayName = "CalendarBase";
|
|
|
4724
4805
|
|
|
4725
4806
|
// src/components/date-time-picker/DateTimePicker.tsx
|
|
4726
4807
|
var import_locale = require("date-fns/locale");
|
|
4727
|
-
var
|
|
4808
|
+
var import_react29 = require("react");
|
|
4728
4809
|
|
|
4729
4810
|
// src/components/date-time-picker/TimePicker.tsx
|
|
4730
4811
|
var import_framer_motion7 = require("framer-motion");
|
|
4731
|
-
var
|
|
4812
|
+
var React32 = __toESM(require("react"));
|
|
4732
4813
|
|
|
4733
4814
|
// src/components/date-time-picker/TimePickerInput.tsx
|
|
4734
|
-
var
|
|
4735
|
-
var
|
|
4815
|
+
var import_react27 = require("@phosphor-icons/react");
|
|
4816
|
+
var import_react28 = __toESM(require("react"));
|
|
4736
4817
|
|
|
4737
4818
|
// src/components/date-time-picker/time-picker-utils.ts
|
|
4738
4819
|
function isValidHour(value) {
|
|
@@ -4874,8 +4955,8 @@ function display12HourValue(hours) {
|
|
|
4874
4955
|
}
|
|
4875
4956
|
|
|
4876
4957
|
// src/components/date-time-picker/TimePickerInput.tsx
|
|
4877
|
-
var
|
|
4878
|
-
var TimePickerInput =
|
|
4958
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
4959
|
+
var TimePickerInput = import_react28.default.forwardRef(
|
|
4879
4960
|
({
|
|
4880
4961
|
className,
|
|
4881
4962
|
type = "tel",
|
|
@@ -4894,10 +4975,10 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
4894
4975
|
label,
|
|
4895
4976
|
...props
|
|
4896
4977
|
}, ref) => {
|
|
4897
|
-
const [flag, setFlag] =
|
|
4898
|
-
const [prevIntKey, setPrevIntKey] =
|
|
4899
|
-
const [isFocused, setIsFocused] =
|
|
4900
|
-
|
|
4978
|
+
const [flag, setFlag] = import_react28.default.useState(false);
|
|
4979
|
+
const [prevIntKey, setPrevIntKey] = import_react28.default.useState("0");
|
|
4980
|
+
const [isFocused, setIsFocused] = import_react28.default.useState(false);
|
|
4981
|
+
import_react28.default.useEffect(() => {
|
|
4901
4982
|
if (flag) {
|
|
4902
4983
|
const timer = setTimeout(() => {
|
|
4903
4984
|
setFlag(false);
|
|
@@ -4905,7 +4986,7 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
4905
4986
|
return () => clearTimeout(timer);
|
|
4906
4987
|
}
|
|
4907
4988
|
}, [flag]);
|
|
4908
|
-
const calculatedValue =
|
|
4989
|
+
const calculatedValue = import_react28.default.useMemo(() => {
|
|
4909
4990
|
return getDateByType(date, picker);
|
|
4910
4991
|
}, [date, picker]);
|
|
4911
4992
|
const calculateNewValue = (key) => {
|
|
@@ -4961,8 +5042,8 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
4961
5042
|
const baseLabel = getPickerLabel();
|
|
4962
5043
|
return `${baseLabel}, valor atual: ${calculatedValue}.`;
|
|
4963
5044
|
};
|
|
4964
|
-
return /* @__PURE__ */ (0,
|
|
4965
|
-
getPickerLabel() && /* @__PURE__ */ (0,
|
|
5045
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "relative group flex flex-col items-center", children: [
|
|
5046
|
+
getPickerLabel() && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
4966
5047
|
"label",
|
|
4967
5048
|
{
|
|
4968
5049
|
htmlFor: id || picker,
|
|
@@ -4970,7 +5051,7 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
4970
5051
|
children: getPickerLabel()
|
|
4971
5052
|
}
|
|
4972
5053
|
),
|
|
4973
|
-
/* @__PURE__ */ (0,
|
|
5054
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
4974
5055
|
"div",
|
|
4975
5056
|
{
|
|
4976
5057
|
className: cn(
|
|
@@ -4978,7 +5059,7 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
4978
5059
|
"transition-all duration-200"
|
|
4979
5060
|
),
|
|
4980
5061
|
children: [
|
|
4981
|
-
showArrows && /* @__PURE__ */ (0,
|
|
5062
|
+
showArrows && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
4982
5063
|
"button",
|
|
4983
5064
|
{
|
|
4984
5065
|
type: "button",
|
|
@@ -4994,11 +5075,11 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
4994
5075
|
),
|
|
4995
5076
|
tabIndex: -1,
|
|
4996
5077
|
"aria-label": `Incrementar ${getPickerLabel().toLowerCase()}`,
|
|
4997
|
-
children: /* @__PURE__ */ (0,
|
|
5078
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react27.CaretUpIcon, { size: 14, className: "sm:w-4 sm:h-4" })
|
|
4998
5079
|
}
|
|
4999
5080
|
),
|
|
5000
|
-
/* @__PURE__ */ (0,
|
|
5001
|
-
/* @__PURE__ */ (0,
|
|
5081
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "relative", children: [
|
|
5082
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
5002
5083
|
"input",
|
|
5003
5084
|
{
|
|
5004
5085
|
ref,
|
|
@@ -5043,9 +5124,9 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
5043
5124
|
...props
|
|
5044
5125
|
}
|
|
5045
5126
|
),
|
|
5046
|
-
isFocused && /* @__PURE__ */ (0,
|
|
5127
|
+
isFocused && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "absolute inset-0 rounded-lg ring-2 ring-primary/20 pointer-events-none animate-pulse" })
|
|
5047
5128
|
] }),
|
|
5048
|
-
showArrows && /* @__PURE__ */ (0,
|
|
5129
|
+
showArrows && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
5049
5130
|
"button",
|
|
5050
5131
|
{
|
|
5051
5132
|
type: "button",
|
|
@@ -5061,7 +5142,7 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
5061
5142
|
),
|
|
5062
5143
|
tabIndex: -1,
|
|
5063
5144
|
"aria-label": `Decrementar ${getPickerLabel().toLowerCase()}`,
|
|
5064
|
-
children: /* @__PURE__ */ (0,
|
|
5145
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_react27.CaretDownIcon, { size: 14, className: "sm:w-4 sm:h-4" })
|
|
5065
5146
|
}
|
|
5066
5147
|
)
|
|
5067
5148
|
]
|
|
@@ -5073,16 +5154,16 @@ var TimePickerInput = import_react27.default.forwardRef(
|
|
|
5073
5154
|
TimePickerInput.displayName = "TimePickerInput";
|
|
5074
5155
|
|
|
5075
5156
|
// src/components/date-time-picker/TimePicker.tsx
|
|
5076
|
-
var
|
|
5157
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
5077
5158
|
function TimePicker({
|
|
5078
5159
|
date,
|
|
5079
5160
|
setDate,
|
|
5080
5161
|
hideSeconds,
|
|
5081
5162
|
enableButton
|
|
5082
5163
|
}) {
|
|
5083
|
-
const minuteRef =
|
|
5084
|
-
const hourRef =
|
|
5085
|
-
const secondRef =
|
|
5164
|
+
const minuteRef = React32.useRef(null);
|
|
5165
|
+
const hourRef = React32.useRef(null);
|
|
5166
|
+
const secondRef = React32.useRef(null);
|
|
5086
5167
|
const containerVariants = {
|
|
5087
5168
|
hidden: { opacity: 0, y: 10 },
|
|
5088
5169
|
visible: {
|
|
@@ -5098,7 +5179,7 @@ function TimePicker({
|
|
|
5098
5179
|
hidden: { opacity: 0, y: 10 },
|
|
5099
5180
|
visible: { opacity: 1, y: 0 }
|
|
5100
5181
|
};
|
|
5101
|
-
return /* @__PURE__ */ (0,
|
|
5182
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
5102
5183
|
import_framer_motion7.motion.div,
|
|
5103
5184
|
{
|
|
5104
5185
|
variants: containerVariants,
|
|
@@ -5106,12 +5187,12 @@ function TimePicker({
|
|
|
5106
5187
|
animate: "visible",
|
|
5107
5188
|
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",
|
|
5108
5189
|
children: [
|
|
5109
|
-
/* @__PURE__ */ (0,
|
|
5190
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
5110
5191
|
import_framer_motion7.motion.div,
|
|
5111
5192
|
{
|
|
5112
5193
|
variants: itemVariants2,
|
|
5113
5194
|
className: "grid gap-1 sm:gap-2 text-center flex-shrink-0 min-w-0",
|
|
5114
|
-
children: /* @__PURE__ */ (0,
|
|
5195
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
5115
5196
|
TimePickerInput,
|
|
5116
5197
|
{
|
|
5117
5198
|
picker: "hours",
|
|
@@ -5124,12 +5205,12 @@ function TimePicker({
|
|
|
5124
5205
|
)
|
|
5125
5206
|
}
|
|
5126
5207
|
),
|
|
5127
|
-
/* @__PURE__ */ (0,
|
|
5208
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
5128
5209
|
import_framer_motion7.motion.div,
|
|
5129
5210
|
{
|
|
5130
5211
|
variants: itemVariants2,
|
|
5131
5212
|
className: "grid gap-1 sm:gap-2 text-center flex-shrink-0 min-w-0",
|
|
5132
|
-
children: /* @__PURE__ */ (0,
|
|
5213
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
5133
5214
|
TimePickerInput,
|
|
5134
5215
|
{
|
|
5135
5216
|
picker: "minutes",
|
|
@@ -5143,7 +5224,7 @@ function TimePicker({
|
|
|
5143
5224
|
)
|
|
5144
5225
|
}
|
|
5145
5226
|
),
|
|
5146
|
-
/* @__PURE__ */ (0,
|
|
5227
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_framer_motion7.AnimatePresence, { children: !hideSeconds && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_jsx_runtime46.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
5147
5228
|
import_framer_motion7.motion.div,
|
|
5148
5229
|
{
|
|
5149
5230
|
variants: itemVariants2,
|
|
@@ -5151,7 +5232,7 @@ function TimePicker({
|
|
|
5151
5232
|
animate: "visible",
|
|
5152
5233
|
exit: "hidden",
|
|
5153
5234
|
className: "grid gap-1 sm:gap-2 text-center flex-shrink-0 min-w-0",
|
|
5154
|
-
children: /* @__PURE__ */ (0,
|
|
5235
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
5155
5236
|
TimePickerInput,
|
|
5156
5237
|
{
|
|
5157
5238
|
picker: "seconds",
|
|
@@ -5170,8 +5251,8 @@ function TimePicker({
|
|
|
5170
5251
|
}
|
|
5171
5252
|
|
|
5172
5253
|
// src/components/date-time-picker/DateTimePicker.tsx
|
|
5173
|
-
var
|
|
5174
|
-
var
|
|
5254
|
+
var import_react30 = require("@phosphor-icons/react");
|
|
5255
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
5175
5256
|
function DateTimePicker({
|
|
5176
5257
|
label,
|
|
5177
5258
|
date,
|
|
@@ -5184,9 +5265,9 @@ function DateTimePicker({
|
|
|
5184
5265
|
disabled,
|
|
5185
5266
|
className
|
|
5186
5267
|
}) {
|
|
5187
|
-
const [internalDate, setInternalDate] = (0,
|
|
5188
|
-
const [open, setOpen] = (0,
|
|
5189
|
-
const [timePickerOpen, setTimePickerOpen] = (0,
|
|
5268
|
+
const [internalDate, setInternalDate] = (0, import_react29.useState)(date);
|
|
5269
|
+
const [open, setOpen] = (0, import_react29.useState)(false);
|
|
5270
|
+
const [timePickerOpen, setTimePickerOpen] = (0, import_react29.useState)(false);
|
|
5190
5271
|
const handleSelect = (newDay) => {
|
|
5191
5272
|
if (!newDay) return;
|
|
5192
5273
|
if (!internalDate) {
|
|
@@ -5215,15 +5296,15 @@ function DateTimePicker({
|
|
|
5215
5296
|
if (!timeFormat) return "PPP";
|
|
5216
5297
|
return `PPP - ${timeFormat}`;
|
|
5217
5298
|
};
|
|
5218
|
-
(0,
|
|
5299
|
+
(0, import_react29.useEffect)(() => {
|
|
5219
5300
|
if (date) {
|
|
5220
5301
|
setInternalDate(date);
|
|
5221
5302
|
}
|
|
5222
5303
|
}, [date, open]);
|
|
5223
|
-
return /* @__PURE__ */ (0,
|
|
5224
|
-
label && /* @__PURE__ */ (0,
|
|
5225
|
-
/* @__PURE__ */ (0,
|
|
5226
|
-
/* @__PURE__ */ (0,
|
|
5304
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: cn("space-y-2 w-full sm:w-auto", className), children: [
|
|
5305
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(LabelBase_default, { children: label }),
|
|
5306
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(PopoverBase, { open, onOpenChange: setOpen, children: [
|
|
5307
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(PopoverTriggerBase, { disabled, asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
5227
5308
|
ButtonBase,
|
|
5228
5309
|
{
|
|
5229
5310
|
variant: "outline",
|
|
@@ -5235,12 +5316,12 @@ function DateTimePicker({
|
|
|
5235
5316
|
!date && "text-muted-foreground"
|
|
5236
5317
|
),
|
|
5237
5318
|
children: [
|
|
5238
|
-
/* @__PURE__ */ (0,
|
|
5239
|
-
/* @__PURE__ */ (0,
|
|
5319
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "truncate flex-1", children: date ? (0, import_date_fns.format)(date, getDisplayFormat(), { locale: import_locale.ptBR }) : "Pick a date" }),
|
|
5320
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react30.CalendarBlankIcon, { className: "flex-shrink-0 w-5 h-5 sm:w-6 sm:h-6" })
|
|
5240
5321
|
]
|
|
5241
5322
|
}
|
|
5242
5323
|
) }),
|
|
5243
|
-
/* @__PURE__ */ (0,
|
|
5324
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5244
5325
|
PopoverContentBase,
|
|
5245
5326
|
{
|
|
5246
5327
|
className: "w-full p-0",
|
|
@@ -5249,8 +5330,8 @@ function DateTimePicker({
|
|
|
5249
5330
|
side: "bottom",
|
|
5250
5331
|
avoidCollisions: true,
|
|
5251
5332
|
collisionPadding: 8,
|
|
5252
|
-
children: /* @__PURE__ */ (0,
|
|
5253
|
-
/* @__PURE__ */ (0,
|
|
5333
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("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: [
|
|
5334
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5254
5335
|
CalendarBase2,
|
|
5255
5336
|
{
|
|
5256
5337
|
mode: "single",
|
|
@@ -5263,13 +5344,13 @@ function DateTimePicker({
|
|
|
5263
5344
|
className: "w-full"
|
|
5264
5345
|
}
|
|
5265
5346
|
),
|
|
5266
|
-
!(hideHour && hideMinute) && /* @__PURE__ */ (0,
|
|
5347
|
+
!(hideHour && hideMinute) && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex justify-center w-full px-2", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
5267
5348
|
PopoverBase,
|
|
5268
5349
|
{
|
|
5269
5350
|
open: timePickerOpen,
|
|
5270
5351
|
onOpenChange: setTimePickerOpen,
|
|
5271
5352
|
children: [
|
|
5272
|
-
/* @__PURE__ */ (0,
|
|
5353
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(PopoverTriggerBase, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
5273
5354
|
ButtonBase,
|
|
5274
5355
|
{
|
|
5275
5356
|
variant: "outline",
|
|
@@ -5285,14 +5366,14 @@ function DateTimePicker({
|
|
|
5285
5366
|
"min-h-[36px] sm:min-h-[40px]"
|
|
5286
5367
|
),
|
|
5287
5368
|
children: [
|
|
5288
|
-
/* @__PURE__ */ (0,
|
|
5289
|
-
/* @__PURE__ */ (0,
|
|
5369
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_react30.ClockIcon, { className: "text-primary/70 flex-shrink-0 w-4 h-4 sm:w-5 sm:h-5" }),
|
|
5370
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-foreground truncate", children: internalDate ? (0, import_date_fns.format)(internalDate, getTimeFormat() || "HH:mm", {
|
|
5290
5371
|
locale: import_locale.ptBR
|
|
5291
5372
|
}) : "00:00" })
|
|
5292
5373
|
]
|
|
5293
5374
|
}
|
|
5294
5375
|
) }),
|
|
5295
|
-
/* @__PURE__ */ (0,
|
|
5376
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5296
5377
|
PopoverContentBase,
|
|
5297
5378
|
{
|
|
5298
5379
|
className: "w-[calc(100vw-2rem)] max-w-sm p-3 sm:p-3 rounded-md",
|
|
@@ -5301,9 +5382,9 @@ function DateTimePicker({
|
|
|
5301
5382
|
sideOffset: 8,
|
|
5302
5383
|
avoidCollisions: true,
|
|
5303
5384
|
collisionPadding: 8,
|
|
5304
|
-
children: /* @__PURE__ */ (0,
|
|
5305
|
-
/* @__PURE__ */ (0,
|
|
5306
|
-
/* @__PURE__ */ (0,
|
|
5385
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-col items-center space-y-2 sm:space-y-3", children: [
|
|
5386
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h4", { className: "text-sm sm:text-base font-medium text-center", children: "Alterar Hor\xE1rio" }),
|
|
5387
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5307
5388
|
TimePicker,
|
|
5308
5389
|
{
|
|
5309
5390
|
setDate: handleTimeChange,
|
|
@@ -5311,7 +5392,7 @@ function DateTimePicker({
|
|
|
5311
5392
|
hideSeconds
|
|
5312
5393
|
}
|
|
5313
5394
|
),
|
|
5314
|
-
/* @__PURE__ */ (0,
|
|
5395
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
5315
5396
|
ButtonBase,
|
|
5316
5397
|
{
|
|
5317
5398
|
size: "sm",
|
|
@@ -5335,7 +5416,7 @@ function DateTimePicker({
|
|
|
5335
5416
|
}
|
|
5336
5417
|
|
|
5337
5418
|
// src/components/selects/Select.tsx
|
|
5338
|
-
var
|
|
5419
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
5339
5420
|
function Select({
|
|
5340
5421
|
items,
|
|
5341
5422
|
groupItems,
|
|
@@ -5344,9 +5425,9 @@ function Select({
|
|
|
5344
5425
|
errorMessage,
|
|
5345
5426
|
testIds = {}
|
|
5346
5427
|
}) {
|
|
5347
|
-
return /* @__PURE__ */ (0,
|
|
5348
|
-
/* @__PURE__ */ (0,
|
|
5349
|
-
/* @__PURE__ */ (0,
|
|
5428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { "data-testid": testIds.root ?? "select-root", children: [
|
|
5429
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(SelectBase, { onValueChange: onChange, "data-testid": testIds.base ?? "select-base", children: [
|
|
5430
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5350
5431
|
SelectTriggerBase,
|
|
5351
5432
|
{
|
|
5352
5433
|
className: cn(
|
|
@@ -5354,7 +5435,7 @@ function Select({
|
|
|
5354
5435
|
errorMessage && "border-red-500"
|
|
5355
5436
|
),
|
|
5356
5437
|
"data-testid": testIds.trigger ?? "select-trigger",
|
|
5357
|
-
children: /* @__PURE__ */ (0,
|
|
5438
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5358
5439
|
SelectValueBase,
|
|
5359
5440
|
{
|
|
5360
5441
|
placeholder,
|
|
@@ -5363,9 +5444,9 @@ function Select({
|
|
|
5363
5444
|
)
|
|
5364
5445
|
}
|
|
5365
5446
|
),
|
|
5366
|
-
/* @__PURE__ */ (0,
|
|
5367
|
-
/* @__PURE__ */ (0,
|
|
5368
|
-
groupItems[key].map((item) => /* @__PURE__ */ (0,
|
|
5447
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ScrollAreaBase, { "data-testid": testIds.scrollarea ?? "select-scrollarea", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SelectContentBase, { "data-testid": testIds.content ?? "select-content", children: groupItems ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_jsx_runtime48.Fragment, { children: Object.keys(groupItems).map((key) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(SelectGroupBase, { "data-testid": testIds.group ?? "select-group", children: [
|
|
5448
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SelectLabelBase, { "data-testid": testIds.label ?? "select-label", children: key }),
|
|
5449
|
+
groupItems[key].map((item) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5369
5450
|
SelectItemBase,
|
|
5370
5451
|
{
|
|
5371
5452
|
value: item.value,
|
|
@@ -5374,7 +5455,7 @@ function Select({
|
|
|
5374
5455
|
},
|
|
5375
5456
|
item.value
|
|
5376
5457
|
))
|
|
5377
|
-
] }, key)) }) : /* @__PURE__ */ (0,
|
|
5458
|
+
] }, key)) }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SelectGroupBase, { "data-testid": testIds.group ?? "select-group", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5378
5459
|
SelectItemBase,
|
|
5379
5460
|
{
|
|
5380
5461
|
value: item.value,
|
|
@@ -5384,7 +5465,7 @@ function Select({
|
|
|
5384
5465
|
item.value
|
|
5385
5466
|
)) }) }) })
|
|
5386
5467
|
] }),
|
|
5387
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
5468
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5388
5469
|
"p",
|
|
5389
5470
|
{
|
|
5390
5471
|
className: "text-sm text-red-500",
|
|
@@ -5395,131 +5476,202 @@ function Select({
|
|
|
5395
5476
|
] });
|
|
5396
5477
|
}
|
|
5397
5478
|
|
|
5398
|
-
// src/components/
|
|
5399
|
-
var
|
|
5400
|
-
var
|
|
5401
|
-
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
5402
|
-
var DestructiveDialog = ({
|
|
5403
|
-
title,
|
|
5404
|
-
description,
|
|
5405
|
-
onConfirm,
|
|
5406
|
-
onCancel,
|
|
5407
|
-
children,
|
|
5408
|
-
triggerContent
|
|
5409
|
-
}) => {
|
|
5410
|
-
const titleId = "destructive-dialog-title";
|
|
5411
|
-
const descriptionId = "destructive-dialog-description";
|
|
5412
|
-
const triggerEl = React32.isValidElement(children) ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(AlertDialogTriggerBase, { asChild: true, children }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(AlertDialogTriggerBase, { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ButtonBase, { variant: "destructive", children: triggerContent ?? "Excluir" }) });
|
|
5413
|
-
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(AlertDialogBase, { children: [
|
|
5414
|
-
triggerEl,
|
|
5415
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
5416
|
-
AlertDialogContentBase,
|
|
5417
|
-
{
|
|
5418
|
-
role: "alertdialog",
|
|
5419
|
-
"aria-modal": "true",
|
|
5420
|
-
"aria-labelledby": titleId,
|
|
5421
|
-
"aria-describedby": descriptionId,
|
|
5422
|
-
className: cn("border border-destructive bg-background"),
|
|
5423
|
-
children: [
|
|
5424
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex items-start gap-4", children: [
|
|
5425
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "flex items-center justify-center w-10 h-10 rounded-full ring-1 ring-destructive/30", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react30.XCircleIcon, { className: "w-6 h-6 text-destructive" }) }),
|
|
5426
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex-1", children: [
|
|
5427
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5428
|
-
AlertDialogTitleBase,
|
|
5429
|
-
{
|
|
5430
|
-
id: titleId,
|
|
5431
|
-
className: "text-lg sm:text-xl font-semibold text-destructive",
|
|
5432
|
-
children: title
|
|
5433
|
-
}
|
|
5434
|
-
),
|
|
5435
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5436
|
-
AlertDialogDescriptionBase,
|
|
5437
|
-
{
|
|
5438
|
-
id: descriptionId,
|
|
5439
|
-
className: "mt-2 text-sm text-muted-foreground",
|
|
5440
|
-
children: description
|
|
5441
|
-
}
|
|
5442
|
-
)
|
|
5443
|
-
] })
|
|
5444
|
-
] }),
|
|
5445
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(AlertDialogFooterBase, { className: "mt-2 flex justify-end gap-3", children: [
|
|
5446
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5447
|
-
AlertDialogCancelBase,
|
|
5448
|
-
{
|
|
5449
|
-
onClick: onCancel,
|
|
5450
|
-
className: cn(
|
|
5451
|
-
buttonVariantsBase({ variant: "outline", size: "default" }),
|
|
5452
|
-
"hover:bg-foreground/5 hover:text-primary hover:opacity-90 hover:shadow-none"
|
|
5453
|
-
),
|
|
5454
|
-
children: "Cancelar"
|
|
5455
|
-
}
|
|
5456
|
-
),
|
|
5457
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
5458
|
-
AlertDialogActionBase,
|
|
5459
|
-
{
|
|
5460
|
-
onClick: onConfirm,
|
|
5461
|
-
className: cn(
|
|
5462
|
-
buttonVariantsBase({ variant: "destructive", size: "default" })
|
|
5463
|
-
),
|
|
5464
|
-
children: "Confirmar"
|
|
5465
|
-
}
|
|
5466
|
-
)
|
|
5467
|
-
] })
|
|
5468
|
-
]
|
|
5469
|
-
}
|
|
5470
|
-
)
|
|
5471
|
-
] });
|
|
5472
|
-
};
|
|
5479
|
+
// src/components/charts/Chart.tsx
|
|
5480
|
+
var import_react35 = require("react");
|
|
5481
|
+
var import_recharts = require("recharts");
|
|
5473
5482
|
|
|
5474
|
-
// src/components/charts/
|
|
5475
|
-
var
|
|
5476
|
-
|
|
5477
|
-
var import_ssr = require("@phosphor-icons/react/dist/ssr");
|
|
5478
|
-
var import_ssr2 = require("@phosphor-icons/react/dist/ssr");
|
|
5479
|
-
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
5480
|
-
var menuVariants = {
|
|
5481
|
-
hidden: { opacity: 0, y: -6, scale: 0.98 },
|
|
5482
|
-
visible: { opacity: 1, y: 0, scale: 1 },
|
|
5483
|
-
exit: { opacity: 0, y: -6, scale: 0.98 }
|
|
5483
|
+
// src/components/charts/utils/helpers.ts
|
|
5484
|
+
var formatFieldName = (fieldName) => {
|
|
5485
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/[_-]/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()).trim();
|
|
5484
5486
|
};
|
|
5485
|
-
var
|
|
5486
|
-
|
|
5487
|
-
|
|
5487
|
+
var detectDataFields = (data, xAxisKey) => {
|
|
5488
|
+
if (!data || data.length === 0) return [];
|
|
5489
|
+
const firstItem = data[0];
|
|
5490
|
+
return Object.keys(firstItem).filter(
|
|
5491
|
+
(key) => key !== xAxisKey && typeof firstItem[key] === "number"
|
|
5492
|
+
);
|
|
5488
5493
|
};
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
}
|
|
5497
|
-
|
|
5498
|
-
const
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5494
|
+
var detectXAxis = (data) => {
|
|
5495
|
+
if (!data || data.length === 0) return "name";
|
|
5496
|
+
const firstItem = data[0];
|
|
5497
|
+
const stringFields = Object.keys(firstItem).filter(
|
|
5498
|
+
(key) => typeof firstItem[key] === "string" || typeof firstItem[key] === "number" && String(firstItem[key]).length <= 4
|
|
5499
|
+
);
|
|
5500
|
+
return stringFields[0] || Object.keys(firstItem)[0] || "name";
|
|
5501
|
+
};
|
|
5502
|
+
var generateAdditionalColors = (baseColors, count) => {
|
|
5503
|
+
const hexToRgb = (hex) => {
|
|
5504
|
+
const clean = hex.replace("#", "");
|
|
5505
|
+
const bigint = parseInt(
|
|
5506
|
+
clean.length === 3 ? clean.split("").map((c) => c + c).join("") : clean,
|
|
5507
|
+
16
|
|
5508
|
+
);
|
|
5509
|
+
return { r: bigint >> 16 & 255, g: bigint >> 8 & 255, b: bigint & 255 };
|
|
5510
|
+
};
|
|
5511
|
+
const rgbToHsl = ({ r, g, b }) => {
|
|
5512
|
+
r /= 255;
|
|
5513
|
+
g /= 255;
|
|
5514
|
+
b /= 255;
|
|
5515
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
5516
|
+
let h = 0;
|
|
5517
|
+
let s = 0;
|
|
5518
|
+
const l = (max + min) / 2;
|
|
5519
|
+
if (max !== min) {
|
|
5520
|
+
const d = max - min;
|
|
5521
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
5522
|
+
switch (max) {
|
|
5523
|
+
case r:
|
|
5524
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
5525
|
+
break;
|
|
5526
|
+
case g:
|
|
5527
|
+
h = (b - r) / d + 2;
|
|
5528
|
+
break;
|
|
5529
|
+
case b:
|
|
5530
|
+
h = (r - g) / d + 4;
|
|
5531
|
+
break;
|
|
5532
|
+
}
|
|
5533
|
+
h /= 6;
|
|
5534
|
+
}
|
|
5535
|
+
return {
|
|
5536
|
+
h: Math.round(h * 360),
|
|
5537
|
+
s: Math.round(s * 100),
|
|
5538
|
+
l: Math.round(l * 100)
|
|
5509
5539
|
};
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5540
|
+
};
|
|
5541
|
+
const hslToHex = (h, s, l) => {
|
|
5542
|
+
s /= 100;
|
|
5543
|
+
l /= 100;
|
|
5544
|
+
const k = (n) => (n + h / 30) % 5;
|
|
5545
|
+
const a = s * Math.min(l, 1 - l);
|
|
5546
|
+
const f = (n) => {
|
|
5547
|
+
const color = l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
5548
|
+
return Math.round(255 * color).toString(16).padStart(2, "0");
|
|
5515
5549
|
};
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5550
|
+
return `#${f(0)}${f(8)}${f(4)}`;
|
|
5551
|
+
};
|
|
5552
|
+
const anchors = baseColors.map((c) => rgbToHsl(hexToRgb(c)));
|
|
5553
|
+
const colors2 = [...baseColors];
|
|
5554
|
+
let i = 0;
|
|
5555
|
+
while (colors2.length < count) {
|
|
5556
|
+
const anchor = anchors[i % anchors.length];
|
|
5557
|
+
const step = Math.floor(i / anchors.length + 1);
|
|
5558
|
+
const hueOffset = step * 25 * (i % 2 === 0 ? 1 : -1);
|
|
5559
|
+
const satOffset = i % 3 === 0 ? -6 : 6;
|
|
5560
|
+
const lightOffset = i % 4 === 0 ? 6 : -4;
|
|
5561
|
+
const newH = (anchor.h + hueOffset + 360) % 360;
|
|
5562
|
+
const newS = Math.max(30, Math.min(95, anchor.s + satOffset));
|
|
5563
|
+
const newL = Math.max(25, Math.min(45, anchor.l + lightOffset));
|
|
5564
|
+
colors2.push(hslToHex(newH, newS, newL));
|
|
5565
|
+
i += 1;
|
|
5566
|
+
}
|
|
5567
|
+
return colors2.slice(0, count);
|
|
5568
|
+
};
|
|
5569
|
+
var niceCeil = (value) => {
|
|
5570
|
+
if (!isFinite(value) || value <= 0) return 1;
|
|
5571
|
+
const pow = Math.pow(10, Math.floor(Math.log10(value)));
|
|
5572
|
+
const normalized = value / pow;
|
|
5573
|
+
const multipliers = [
|
|
5574
|
+
1,
|
|
5575
|
+
1.25,
|
|
5576
|
+
1.5,
|
|
5577
|
+
2,
|
|
5578
|
+
2.5,
|
|
5579
|
+
3,
|
|
5580
|
+
4,
|
|
5581
|
+
5,
|
|
5582
|
+
7.5,
|
|
5583
|
+
10,
|
|
5584
|
+
15,
|
|
5585
|
+
20,
|
|
5586
|
+
25,
|
|
5587
|
+
50,
|
|
5588
|
+
100
|
|
5589
|
+
];
|
|
5590
|
+
for (const m of multipliers) {
|
|
5591
|
+
if (m >= normalized) return Math.ceil(m * pow);
|
|
5592
|
+
}
|
|
5593
|
+
return Math.ceil(100 * pow);
|
|
5594
|
+
};
|
|
5595
|
+
var compactTick = (value) => {
|
|
5596
|
+
if (value >= 1e9)
|
|
5597
|
+
return (value / 1e9).toFixed(1).replace(/\.0$/, "") + "B";
|
|
5598
|
+
if (value >= 1e6)
|
|
5599
|
+
return (value / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
5600
|
+
if (value >= 1e3) return (value / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
5601
|
+
return String(value);
|
|
5602
|
+
};
|
|
5603
|
+
var resolveContainerPaddingLeft = (padding, containerPaddingLeft, defaultLeft = 16) => {
|
|
5604
|
+
if (typeof padding === "number") return padding;
|
|
5605
|
+
if (padding && typeof padding === "object" && padding.left != null)
|
|
5606
|
+
return padding.left;
|
|
5607
|
+
if (typeof containerPaddingLeft === "number") return containerPaddingLeft;
|
|
5608
|
+
return defaultLeft;
|
|
5609
|
+
};
|
|
5610
|
+
var resolveChartMargins = (margins, chartMargins, showLabels) => {
|
|
5611
|
+
const defaultRight = 30;
|
|
5612
|
+
const defaultLeft = 20;
|
|
5613
|
+
const topDefault = showLabels ? 48 : 20;
|
|
5614
|
+
const bottomDefault = 5;
|
|
5615
|
+
return {
|
|
5616
|
+
top: margins?.top ?? chartMargins?.top ?? topDefault,
|
|
5617
|
+
right: margins?.right ?? chartMargins?.right ?? defaultRight,
|
|
5618
|
+
left: margins?.left ?? chartMargins?.left ?? defaultLeft,
|
|
5619
|
+
bottom: margins?.bottom ?? chartMargins?.bottom ?? bottomDefault
|
|
5620
|
+
};
|
|
5621
|
+
};
|
|
5622
|
+
|
|
5623
|
+
// src/components/charts/Chart.tsx
|
|
5624
|
+
var import_sonner2 = require("sonner");
|
|
5625
|
+
|
|
5626
|
+
// src/components/charts/components/controls/PeriodsDropdown.tsx
|
|
5627
|
+
var import_react31 = require("react");
|
|
5628
|
+
var import_framer_motion8 = require("framer-motion");
|
|
5629
|
+
var import_ssr = require("@phosphor-icons/react/dist/ssr");
|
|
5630
|
+
var import_ssr2 = require("@phosphor-icons/react/dist/ssr");
|
|
5631
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
5632
|
+
var menuVariants = {
|
|
5633
|
+
hidden: { opacity: 0, y: -6, scale: 0.98 },
|
|
5634
|
+
visible: { opacity: 1, y: 0, scale: 1 },
|
|
5635
|
+
exit: { opacity: 0, y: -6, scale: 0.98 }
|
|
5636
|
+
};
|
|
5637
|
+
var itemVariants = {
|
|
5638
|
+
hidden: { opacity: 0, x: -6 },
|
|
5639
|
+
visible: { opacity: 1, x: 0 }
|
|
5640
|
+
};
|
|
5641
|
+
function PeriodsDropdown({
|
|
5642
|
+
processedData,
|
|
5643
|
+
onOpenPeriod,
|
|
5644
|
+
rightOffset,
|
|
5645
|
+
topOffset,
|
|
5646
|
+
activePeriod,
|
|
5647
|
+
activePeriods
|
|
5648
|
+
}) {
|
|
5649
|
+
const periods = processedData.map((d) => String(d.name));
|
|
5650
|
+
const [open, setOpen] = (0, import_react31.useState)(false);
|
|
5651
|
+
const wrapperRef = (0, import_react31.useRef)(null);
|
|
5652
|
+
const firstItemRef = (0, import_react31.useRef)(null);
|
|
5653
|
+
const listRef = (0, import_react31.useRef)(null);
|
|
5654
|
+
(0, import_react31.useEffect)(() => {
|
|
5655
|
+
const handleClickOutside = (e) => {
|
|
5656
|
+
if (!wrapperRef.current) return;
|
|
5657
|
+
if (!wrapperRef.current.contains(e.target)) setOpen(false);
|
|
5658
|
+
};
|
|
5659
|
+
const handleEscape = (e) => {
|
|
5660
|
+
if (e.key === "Escape") setOpen(false);
|
|
5661
|
+
};
|
|
5662
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
5663
|
+
document.addEventListener("keydown", handleEscape);
|
|
5664
|
+
return () => {
|
|
5665
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
5666
|
+
document.removeEventListener("keydown", handleEscape);
|
|
5667
|
+
};
|
|
5668
|
+
}, []);
|
|
5669
|
+
(0, import_react31.useEffect)(() => {
|
|
5670
|
+
if (open && firstItemRef.current) {
|
|
5671
|
+
firstItemRef.current.focus();
|
|
5672
|
+
}
|
|
5673
|
+
}, [open]);
|
|
5674
|
+
function handleSelect(p) {
|
|
5523
5675
|
onOpenPeriod(p);
|
|
5524
5676
|
setOpen(false);
|
|
5525
5677
|
}
|
|
@@ -6594,269 +6746,2217 @@ var TooltipSimple = ({
|
|
|
6594
6746
|
};
|
|
6595
6747
|
var TooltipSimple_default = TooltipSimple;
|
|
6596
6748
|
|
|
6597
|
-
// src/components/charts/utils/
|
|
6598
|
-
var
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6749
|
+
// src/components/charts/utils/pillLabelRenderer.tsx
|
|
6750
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
6751
|
+
var formatCompactNumber = (value) => {
|
|
6752
|
+
const isNegative = value < 0;
|
|
6753
|
+
const absValue = Math.abs(value);
|
|
6754
|
+
let formatted;
|
|
6755
|
+
if (absValue >= 1e9) {
|
|
6756
|
+
formatted = (absValue / 1e9).toFixed(1).replace(/\.0$/, "") + "B";
|
|
6757
|
+
} else if (absValue >= 1e6) {
|
|
6758
|
+
formatted = (absValue / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
|
|
6759
|
+
} else if (absValue >= 1e3) {
|
|
6760
|
+
formatted = (absValue / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
|
|
6761
|
+
} else {
|
|
6762
|
+
formatted = absValue.toString();
|
|
6763
|
+
}
|
|
6764
|
+
return isNegative ? `-${formatted}` : formatted;
|
|
6607
6765
|
};
|
|
6608
|
-
var
|
|
6609
|
-
if (
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
);
|
|
6614
|
-
return stringFields[0] || Object.keys(firstItem)[0] || "name";
|
|
6766
|
+
var parseNumber = (v) => {
|
|
6767
|
+
if (typeof v === "number") return v;
|
|
6768
|
+
if (typeof v === "string" && v.trim() !== "" && !Number.isNaN(Number(v)))
|
|
6769
|
+
return Number(v);
|
|
6770
|
+
return void 0;
|
|
6615
6771
|
};
|
|
6616
|
-
var
|
|
6617
|
-
|
|
6618
|
-
const
|
|
6619
|
-
const
|
|
6620
|
-
|
|
6621
|
-
|
|
6772
|
+
var renderPillLabel = (color, variant) => {
|
|
6773
|
+
return (props) => {
|
|
6774
|
+
const { x, y, value } = props;
|
|
6775
|
+
const text = typeof value === "number" ? formatCompactNumber(value) : String(value ?? "");
|
|
6776
|
+
const paddingX = 8;
|
|
6777
|
+
const approxCharWidth = 7;
|
|
6778
|
+
const pillWidth = Math.max(
|
|
6779
|
+
40,
|
|
6780
|
+
String(text).length * approxCharWidth + paddingX * 2
|
|
6622
6781
|
);
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6782
|
+
const pillHeight = 20;
|
|
6783
|
+
const xNum = parseNumber(x);
|
|
6784
|
+
const px = parseNumber(props.x);
|
|
6785
|
+
const pWidth = parseNumber(props.width);
|
|
6786
|
+
const vb = props.viewBox;
|
|
6787
|
+
const cxNum = parseNumber(props.cx);
|
|
6788
|
+
let centerX;
|
|
6789
|
+
if (typeof px === "number" && typeof pWidth === "number") {
|
|
6790
|
+
centerX = px + pWidth / 2;
|
|
6791
|
+
} else if (typeof xNum === "number" && typeof pWidth === "number") {
|
|
6792
|
+
centerX = xNum + pWidth / 2;
|
|
6793
|
+
} else if (typeof cxNum === "number") {
|
|
6794
|
+
centerX = cxNum;
|
|
6795
|
+
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number" && typeof props.index === "number") {
|
|
6796
|
+
const approxCols = Math.max(1, props.index + 1);
|
|
6797
|
+
const colWidth = vb.width / approxCols;
|
|
6798
|
+
centerX = vb.x + colWidth * (props.index + 0.5);
|
|
6799
|
+
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number") {
|
|
6800
|
+
centerX = vb.x + vb.width / 2;
|
|
6801
|
+
} else {
|
|
6802
|
+
centerX = typeof props.index === "number" ? props.index * 40 + 24 : 0;
|
|
6803
|
+
}
|
|
6804
|
+
if (vb && typeof vb.x === "number" && typeof vb.width === "number") {
|
|
6805
|
+
const minX = vb.x + 0 + pillWidth / 22;
|
|
6806
|
+
const maxX = vb.x + vb.width - 2 - pillWidth / 2;
|
|
6807
|
+
centerX = Math.max(minX, Math.min(maxX, centerX));
|
|
6808
|
+
}
|
|
6809
|
+
const yNum = parseNumber(y);
|
|
6810
|
+
const py = parseNumber(props.y);
|
|
6811
|
+
const cyNum = parseNumber(props.cy);
|
|
6812
|
+
const centerY = yNum ?? (typeof py === "number" ? py : vb && typeof vb.y === "number" && typeof vb.height === "number" ? vb.y + vb.height / 2 : typeof cyNum === "number" ? cyNum : 0);
|
|
6813
|
+
const rectX = centerX - pillWidth / 2;
|
|
6814
|
+
const rectY = centerY - pillHeight - 6;
|
|
6815
|
+
const textX = centerX;
|
|
6816
|
+
const textY = rectY + pillHeight / 2 + 3;
|
|
6817
|
+
const rectFill = variant === "filled" ? color : variant === "soft" ? `${color}20` : "#ffffff";
|
|
6818
|
+
const rectStroke = variant === "outline" ? `${color}CC` : void 0;
|
|
6819
|
+
const numValue = parseNumber(value);
|
|
6820
|
+
const isNegative = typeof numValue === "number" && numValue < 0;
|
|
6821
|
+
let textColor;
|
|
6822
|
+
if (isNegative) {
|
|
6823
|
+
textColor = "#dc2626";
|
|
6824
|
+
} else {
|
|
6825
|
+
if (variant === "filled") {
|
|
6826
|
+
textColor = "#ffffff";
|
|
6827
|
+
} else {
|
|
6828
|
+
textColor = "#374151";
|
|
6646
6829
|
}
|
|
6647
|
-
h /= 6;
|
|
6648
6830
|
}
|
|
6649
|
-
return {
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("g", { children: [
|
|
6832
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
6833
|
+
"rect",
|
|
6834
|
+
{
|
|
6835
|
+
x: rectX,
|
|
6836
|
+
y: rectY,
|
|
6837
|
+
rx: pillHeight / 2,
|
|
6838
|
+
width: pillWidth,
|
|
6839
|
+
height: pillHeight,
|
|
6840
|
+
fill: rectFill,
|
|
6841
|
+
stroke: rectStroke,
|
|
6842
|
+
strokeWidth: rectStroke ? 1 : 0
|
|
6843
|
+
}
|
|
6844
|
+
),
|
|
6845
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
6846
|
+
"text",
|
|
6847
|
+
{
|
|
6848
|
+
x: textX,
|
|
6849
|
+
y: textY - 3,
|
|
6850
|
+
fill: textColor,
|
|
6851
|
+
fontSize: 13,
|
|
6852
|
+
fontWeight: 700,
|
|
6853
|
+
textAnchor: "middle",
|
|
6854
|
+
dominantBaseline: "central",
|
|
6855
|
+
letterSpacing: 0.2,
|
|
6856
|
+
children: text
|
|
6857
|
+
}
|
|
6858
|
+
)
|
|
6859
|
+
] });
|
|
6860
|
+
};
|
|
6861
|
+
};
|
|
6862
|
+
var pillLabelRenderer_default = renderPillLabel;
|
|
6863
|
+
|
|
6864
|
+
// src/components/charts/Chart.tsx
|
|
6865
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
6866
|
+
var DEFAULT_COLORS = ["#55af7d", "#8e68ff", "#2273e1"];
|
|
6867
|
+
var Chart = ({
|
|
6868
|
+
data,
|
|
6869
|
+
series,
|
|
6870
|
+
className,
|
|
6871
|
+
height = 350,
|
|
6872
|
+
width = "100%",
|
|
6873
|
+
colors: colors2 = DEFAULT_COLORS,
|
|
6874
|
+
gridColor,
|
|
6875
|
+
showGrid = true,
|
|
6876
|
+
showTooltip = true,
|
|
6877
|
+
showLegend = true,
|
|
6878
|
+
title,
|
|
6879
|
+
titlePosition = "left",
|
|
6880
|
+
showLabels = false,
|
|
6881
|
+
xAxis,
|
|
6882
|
+
labelMap,
|
|
6883
|
+
enableHighlights = false,
|
|
6884
|
+
enableShowOnly = false,
|
|
6885
|
+
enablePeriodsDropdown = false,
|
|
6886
|
+
enableDraggableTooltips = false,
|
|
6887
|
+
showTooltipTotal = false,
|
|
6888
|
+
maxTooltips = 5,
|
|
6889
|
+
chartMargin
|
|
6890
|
+
}) => {
|
|
6891
|
+
const smartConfig = (0, import_react35.useMemo)(() => {
|
|
6892
|
+
const resolvedXAxisKey = typeof xAxis === "string" ? xAxis : xAxis && xAxis.dataKey || detectXAxis(data);
|
|
6893
|
+
const xAxisConfig2 = typeof xAxis === "string" ? {
|
|
6894
|
+
dataKey: resolvedXAxisKey,
|
|
6895
|
+
label: formatFieldName(resolvedXAxisKey),
|
|
6896
|
+
autoLabel: true
|
|
6897
|
+
} : {
|
|
6898
|
+
dataKey: resolvedXAxisKey,
|
|
6899
|
+
label: xAxis?.label ?? formatFieldName(resolvedXAxisKey),
|
|
6900
|
+
formatter: xAxis?.formatter,
|
|
6901
|
+
autoLabel: xAxis?.autoLabel ?? true
|
|
6902
|
+
};
|
|
6903
|
+
const detectedFields = detectDataFields(data, xAxisConfig2.dataKey);
|
|
6904
|
+
const mapperConfig2 = detectedFields.reduce((acc, field) => {
|
|
6905
|
+
acc[field] = {
|
|
6906
|
+
label: labelMap?.[field] ?? formatFieldName(field),
|
|
6907
|
+
type: "number",
|
|
6908
|
+
visible: true
|
|
6909
|
+
};
|
|
6910
|
+
return acc;
|
|
6911
|
+
}, {});
|
|
6912
|
+
return { xAxisConfig: xAxisConfig2, mapperConfig: mapperConfig2 };
|
|
6913
|
+
}, [data, xAxis, labelMap]);
|
|
6914
|
+
const { xAxisConfig, mapperConfig } = smartConfig;
|
|
6915
|
+
const [activeTooltips, setActiveTooltips] = (0, import_react35.useState)([]);
|
|
6916
|
+
const [highlightedSeries, setHighlightedSeries] = (0, import_react35.useState)(
|
|
6917
|
+
/* @__PURE__ */ new Set()
|
|
6918
|
+
);
|
|
6919
|
+
const [showOnlyHighlighted, setShowOnlyHighlighted] = (0, import_react35.useState)(false);
|
|
6920
|
+
(0, import_react35.useEffect)(() => {
|
|
6921
|
+
if (highlightedSeries.size === 0 && showOnlyHighlighted) {
|
|
6922
|
+
setShowOnlyHighlighted(false);
|
|
6923
|
+
}
|
|
6924
|
+
}, [highlightedSeries, showOnlyHighlighted]);
|
|
6925
|
+
const processedData = data.map((item) => ({
|
|
6926
|
+
...item,
|
|
6927
|
+
name: String(item[xAxisConfig.dataKey] || "N/A")
|
|
6928
|
+
}));
|
|
6929
|
+
const wrapperRef = (0, import_react35.useRef)(null);
|
|
6930
|
+
const [measuredWidth, setMeasuredWidth] = (0, import_react35.useState)(null);
|
|
6931
|
+
(0, import_react35.useLayoutEffect)(() => {
|
|
6932
|
+
const el = wrapperRef.current;
|
|
6933
|
+
if (!el) return;
|
|
6934
|
+
const ro = new ResizeObserver((entries) => {
|
|
6935
|
+
const r = entries[0];
|
|
6936
|
+
if (r && typeof r.contentRect.width === "number") {
|
|
6937
|
+
setMeasuredWidth(Math.round(r.contentRect.width));
|
|
6938
|
+
}
|
|
6939
|
+
});
|
|
6940
|
+
ro.observe(el);
|
|
6941
|
+
setMeasuredWidth(Math.round(el.getBoundingClientRect().width));
|
|
6942
|
+
return () => ro.disconnect();
|
|
6943
|
+
}, []);
|
|
6944
|
+
const seriesOrder = [];
|
|
6945
|
+
if (series) {
|
|
6946
|
+
if (series.bar)
|
|
6947
|
+
series.bar.forEach((k) => seriesOrder.push({ type: "bar", key: k }));
|
|
6948
|
+
if (series.line)
|
|
6949
|
+
series.line.forEach((k) => seriesOrder.push({ type: "line", key: k }));
|
|
6950
|
+
if (series.area)
|
|
6951
|
+
series.area.forEach((k) => seriesOrder.push({ type: "area", key: k }));
|
|
6952
|
+
} else {
|
|
6953
|
+
Object.keys(mapperConfig).forEach(
|
|
6954
|
+
(k) => seriesOrder.push({ type: "bar", key: k })
|
|
6955
|
+
);
|
|
6956
|
+
}
|
|
6957
|
+
const allKeys = seriesOrder.map((s) => s.key).filter(Boolean);
|
|
6958
|
+
const generateColors = (0, import_react35.useCallback)(
|
|
6959
|
+
(dataKeys) => {
|
|
6960
|
+
const colorMap = {};
|
|
6961
|
+
const allColors = generateAdditionalColors(colors2, dataKeys.length);
|
|
6962
|
+
dataKeys.forEach((key, index) => {
|
|
6963
|
+
colorMap[key] = mapperConfig[key]?.color || allColors[index] || colors2[index % colors2.length];
|
|
6964
|
+
});
|
|
6965
|
+
return colorMap;
|
|
6966
|
+
},
|
|
6967
|
+
[colors2, mapperConfig]
|
|
6968
|
+
);
|
|
6969
|
+
const finalColors = (0, import_react35.useMemo)(
|
|
6970
|
+
() => generateColors(allKeys),
|
|
6971
|
+
[generateColors, allKeys]
|
|
6972
|
+
);
|
|
6973
|
+
const adaptDataForTooltip = (0, import_react35.useCallback)(
|
|
6974
|
+
(universalData) => ({
|
|
6975
|
+
...universalData,
|
|
6976
|
+
name: String(universalData[xAxisConfig.dataKey] || "N/A")
|
|
6977
|
+
}),
|
|
6978
|
+
[xAxisConfig.dataKey]
|
|
6979
|
+
);
|
|
6980
|
+
const activePeriods = (0, import_react35.useMemo)(
|
|
6981
|
+
() => activeTooltips.map((t) => adaptDataForTooltip(t.data).name),
|
|
6982
|
+
[activeTooltips, adaptDataForTooltip]
|
|
6983
|
+
);
|
|
6984
|
+
(0, import_react35.useEffect)(() => {
|
|
6985
|
+
window.dispatchEvent(new Event("recountTooltips"));
|
|
6986
|
+
}, [activeTooltips.length]);
|
|
6987
|
+
const toggleHighlight = (0, import_react35.useCallback)((key) => {
|
|
6988
|
+
setHighlightedSeries((prev) => {
|
|
6989
|
+
const next = new Set(prev);
|
|
6990
|
+
if (next.has(key)) next.delete(key);
|
|
6991
|
+
else next.add(key);
|
|
6992
|
+
return next;
|
|
6993
|
+
});
|
|
6994
|
+
}, []);
|
|
6995
|
+
const maxDataValue = (0, import_react35.useMemo)(() => {
|
|
6996
|
+
let max = 0;
|
|
6997
|
+
const numericKeys = allKeys;
|
|
6998
|
+
for (const row of processedData) {
|
|
6999
|
+
const r = row;
|
|
7000
|
+
for (const key of numericKeys) {
|
|
7001
|
+
const v = r[key];
|
|
7002
|
+
if (typeof v === "number" && Number.isFinite(v) && v > max) max = v;
|
|
7003
|
+
}
|
|
7004
|
+
}
|
|
7005
|
+
return max;
|
|
7006
|
+
}, [processedData, allKeys]);
|
|
7007
|
+
const minDataValue = (0, import_react35.useMemo)(() => {
|
|
7008
|
+
let min = 0;
|
|
7009
|
+
const numericKeys = allKeys;
|
|
7010
|
+
for (const row of processedData) {
|
|
7011
|
+
const r = row;
|
|
7012
|
+
for (const key of numericKeys) {
|
|
7013
|
+
const v = r[key];
|
|
7014
|
+
if (typeof v === "number" && Number.isFinite(v) && v < min)
|
|
7015
|
+
min = v;
|
|
7016
|
+
}
|
|
7017
|
+
}
|
|
7018
|
+
return min;
|
|
7019
|
+
}, [processedData, allKeys]);
|
|
7020
|
+
const niceMax = (0, import_react35.useMemo)(() => {
|
|
7021
|
+
let padding = 0.08;
|
|
7022
|
+
if (maxDataValue > 1e6) padding = 0.05;
|
|
7023
|
+
if (maxDataValue > 1e7) padding = 0.03;
|
|
7024
|
+
if (maxDataValue === 0) padding = 0.12;
|
|
7025
|
+
const padded = maxDataValue * (1 + padding);
|
|
7026
|
+
return niceCeil(padded);
|
|
7027
|
+
}, [maxDataValue]);
|
|
7028
|
+
const computedWidth = (0, import_react35.useMemo)(() => {
|
|
7029
|
+
if (typeof width === "number") return width;
|
|
7030
|
+
const points = Math.max(1, processedData.length);
|
|
7031
|
+
const barCount = series?.bar?.length ?? 0;
|
|
7032
|
+
const lineCount = series?.line?.length ?? 0;
|
|
7033
|
+
const areaCount = series?.area?.length ?? 0;
|
|
7034
|
+
const basePerPoint = 60;
|
|
7035
|
+
const perBarExtra = barCount > 0 ? Math.max(0, barCount - 1) * 8 : 0;
|
|
7036
|
+
const perOtherExtra = (lineCount + areaCount) * 4;
|
|
7037
|
+
let sizeFactor = 1;
|
|
7038
|
+
if (niceMax > 1e5) sizeFactor = 1.1;
|
|
7039
|
+
if (niceMax > 1e6) sizeFactor = 1.2;
|
|
7040
|
+
if (niceMax > 1e7) sizeFactor = 1.3;
|
|
7041
|
+
const perPoint = Math.round(
|
|
7042
|
+
(basePerPoint + perBarExtra + perOtherExtra) * sizeFactor
|
|
7043
|
+
);
|
|
7044
|
+
const marginExtra = 120;
|
|
7045
|
+
const calculated = points * perPoint + marginExtra;
|
|
7046
|
+
const minWidth = 300;
|
|
7047
|
+
const maxWidth = 1800;
|
|
7048
|
+
return Math.max(minWidth, Math.min(maxWidth, calculated));
|
|
7049
|
+
}, [
|
|
7050
|
+
width,
|
|
7051
|
+
processedData.length,
|
|
7052
|
+
series?.bar?.length,
|
|
7053
|
+
series?.line?.length,
|
|
7054
|
+
series?.area?.length,
|
|
7055
|
+
niceMax
|
|
7056
|
+
]);
|
|
7057
|
+
const toggleTooltip = (0, import_react35.useCallback)(
|
|
7058
|
+
(tooltipId, data2, basePosition) => {
|
|
7059
|
+
const existingIndex = activeTooltips.findIndex((t) => t.id === tooltipId);
|
|
7060
|
+
if (existingIndex !== -1) {
|
|
7061
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== tooltipId));
|
|
7062
|
+
} else {
|
|
7063
|
+
if (activeTooltips.length >= maxTooltips) {
|
|
7064
|
+
import_sonner2.toast.warning(
|
|
7065
|
+
`Limite de ${maxTooltips} janelas de informa\xE7\xE3o atingido. A mais antiga ser\xE1 substitu\xEDda.`
|
|
7066
|
+
);
|
|
7067
|
+
}
|
|
7068
|
+
const offsetIndex = activeTooltips.length;
|
|
7069
|
+
const gap = 28;
|
|
7070
|
+
const newTooltip = {
|
|
7071
|
+
id: tooltipId,
|
|
7072
|
+
data: data2,
|
|
7073
|
+
position: {
|
|
7074
|
+
top: basePosition.top + offsetIndex * gap,
|
|
7075
|
+
left: basePosition.left + offsetIndex * gap
|
|
7076
|
+
}
|
|
7077
|
+
};
|
|
7078
|
+
setActiveTooltips((prev) => {
|
|
7079
|
+
const next = [...prev, newTooltip];
|
|
7080
|
+
return next.length > maxTooltips ? next.slice(1) : next;
|
|
7081
|
+
});
|
|
7082
|
+
}
|
|
7083
|
+
},
|
|
7084
|
+
[activeTooltips, maxTooltips]
|
|
7085
|
+
);
|
|
7086
|
+
const handleChartClick = (0, import_react35.useCallback)(
|
|
7087
|
+
(e) => {
|
|
7088
|
+
if (!enableDraggableTooltips) return;
|
|
7089
|
+
const ev = e;
|
|
7090
|
+
if (ev?.activePayload?.length) {
|
|
7091
|
+
const clickedData = ev.activePayload[0].payload;
|
|
7092
|
+
const xAxisValue = clickedData[xAxisConfig.dataKey] || clickedData.name || "N/A";
|
|
7093
|
+
const tooltipId = String(xAxisValue);
|
|
7094
|
+
toggleTooltip(tooltipId, clickedData, {
|
|
7095
|
+
top: (ev.chartY || 100) - 10,
|
|
7096
|
+
left: (ev.chartX || 100) - 100
|
|
7097
|
+
});
|
|
7098
|
+
} else {
|
|
7099
|
+
setActiveTooltips([]);
|
|
7100
|
+
}
|
|
7101
|
+
},
|
|
7102
|
+
[enableDraggableTooltips, xAxisConfig.dataKey, toggleTooltip]
|
|
7103
|
+
);
|
|
7104
|
+
const handleBarClick = (0, import_react35.useCallback)(
|
|
7105
|
+
(data2, index, event) => {
|
|
7106
|
+
if (!enableDraggableTooltips) return;
|
|
7107
|
+
event.stopPropagation();
|
|
7108
|
+
const xAxisValue = data2[xAxisConfig.dataKey] || "N/A";
|
|
7109
|
+
const tooltipId = String(xAxisValue);
|
|
7110
|
+
const rect = event.target.getBoundingClientRect();
|
|
7111
|
+
toggleTooltip(tooltipId, data2, {
|
|
7112
|
+
top: Math.max(8, rect.top - 10),
|
|
7113
|
+
left: rect.right + 10
|
|
7114
|
+
});
|
|
7115
|
+
},
|
|
7116
|
+
[enableDraggableTooltips, xAxisConfig.dataKey, toggleTooltip]
|
|
7117
|
+
);
|
|
7118
|
+
const handleSeriesClick = (0, import_react35.useCallback)(
|
|
7119
|
+
(...args) => {
|
|
7120
|
+
if (args.length >= 3) {
|
|
7121
|
+
const [data2, index, event] = args;
|
|
7122
|
+
handleBarClick(data2, index, event);
|
|
7123
|
+
return;
|
|
7124
|
+
}
|
|
7125
|
+
handleChartClick(args[0]);
|
|
7126
|
+
},
|
|
7127
|
+
[handleBarClick, handleChartClick]
|
|
7128
|
+
);
|
|
7129
|
+
const onTooltipPositionChange = (0, import_react35.useCallback)(
|
|
7130
|
+
(id, position) => {
|
|
7131
|
+
setActiveTooltips(
|
|
7132
|
+
(prev) => prev.map((t) => t.id === id ? { ...t, position } : t)
|
|
7133
|
+
);
|
|
7134
|
+
},
|
|
7135
|
+
[]
|
|
7136
|
+
);
|
|
7137
|
+
const titleClassName = (0, import_react35.useMemo)(
|
|
7138
|
+
() => "text-xl font-semibold text-foreground mb-3",
|
|
7139
|
+
[]
|
|
7140
|
+
);
|
|
7141
|
+
const finalEnableHighlights = enableHighlights;
|
|
7142
|
+
const finalEnableShowOnly = enableShowOnly;
|
|
7143
|
+
const finalEnablePeriodsDropdown = enablePeriodsDropdown && enableDraggableTooltips;
|
|
7144
|
+
const defaultChartRightMargin = 30;
|
|
7145
|
+
const defaultChartLeftMargin = 0;
|
|
7146
|
+
const containerPaddingLeft = 16;
|
|
7147
|
+
const finalChartRightMargin = chartMargin?.right ?? defaultChartRightMargin;
|
|
7148
|
+
const finalChartLeftMargin = chartMargin?.left ?? defaultChartLeftMargin;
|
|
7149
|
+
const finalChartTopMargin = chartMargin?.top ?? (showLabels ? 48 : 20);
|
|
7150
|
+
const finalChartBottomMargin = chartMargin?.bottom ?? 5;
|
|
7151
|
+
const measuredInner = measuredWidth ? Math.max(0, measuredWidth - 32) : void 0;
|
|
7152
|
+
const effectiveChartWidth = typeof width === "number" ? width : measuredInner ?? computedWidth;
|
|
7153
|
+
const chartInnerWidth = effectiveChartWidth - finalChartLeftMargin - finalChartRightMargin;
|
|
7154
|
+
const openTooltipForPeriod = (0, import_react35.useCallback)(
|
|
7155
|
+
(periodName) => {
|
|
7156
|
+
if (!enableDraggableTooltips) return;
|
|
7157
|
+
const row = processedData.find((r) => String(r.name) === periodName);
|
|
7158
|
+
if (!row) return;
|
|
7159
|
+
const tooltipId = String(periodName);
|
|
7160
|
+
const existingIndex = activeTooltips.findIndex((t) => t.id === tooltipId);
|
|
7161
|
+
if (existingIndex !== -1) {
|
|
7162
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== tooltipId));
|
|
7163
|
+
return;
|
|
7164
|
+
}
|
|
7165
|
+
if (activeTooltips.length >= maxTooltips) {
|
|
7166
|
+
import_sonner2.toast.warning(
|
|
7167
|
+
`Limite de ${maxTooltips} janelas de informa\xE7\xE3o atingido. A mais antiga ser\xE1 substitu\xEDda.`
|
|
7168
|
+
);
|
|
7169
|
+
}
|
|
7170
|
+
const offsetIndex = activeTooltips.length;
|
|
7171
|
+
const availableWidth = typeof width === "number" ? width : measuredInner ?? computedWidth;
|
|
7172
|
+
const gap = 28;
|
|
7173
|
+
const leftGap = 28;
|
|
7174
|
+
const newTooltip = {
|
|
7175
|
+
id: tooltipId,
|
|
7176
|
+
data: row,
|
|
7177
|
+
position: {
|
|
7178
|
+
top: 48 + offsetIndex * gap,
|
|
7179
|
+
left: Math.max(120, availableWidth - 280 - offsetIndex * leftGap)
|
|
7180
|
+
}
|
|
7181
|
+
};
|
|
7182
|
+
setActiveTooltips((prev) => {
|
|
7183
|
+
const next = [...prev, newTooltip];
|
|
7184
|
+
return next.length > maxTooltips ? next.slice(1) : next;
|
|
7185
|
+
});
|
|
7186
|
+
},
|
|
7187
|
+
[
|
|
7188
|
+
enableDraggableTooltips,
|
|
7189
|
+
processedData,
|
|
7190
|
+
activeTooltips,
|
|
7191
|
+
width,
|
|
7192
|
+
measuredInner,
|
|
7193
|
+
computedWidth,
|
|
7194
|
+
maxTooltips
|
|
7195
|
+
]
|
|
7196
|
+
);
|
|
7197
|
+
if (!data) return null;
|
|
7198
|
+
if (Array.isArray(data) && data.length === 0) {
|
|
7199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7200
|
+
"div",
|
|
7201
|
+
{
|
|
7202
|
+
className: cn(
|
|
7203
|
+
"rounded-lg bg-card p-4 relative w-full text-muted-foreground"
|
|
7204
|
+
),
|
|
7205
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7206
|
+
"div",
|
|
7207
|
+
{
|
|
7208
|
+
style: {
|
|
7209
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`
|
|
7210
|
+
},
|
|
7211
|
+
children: "Sem dados para exibir"
|
|
7212
|
+
}
|
|
7213
|
+
)
|
|
7214
|
+
}
|
|
7215
|
+
);
|
|
7216
|
+
}
|
|
7217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7218
|
+
"div",
|
|
7219
|
+
{
|
|
7220
|
+
ref: wrapperRef,
|
|
7221
|
+
style: {
|
|
7222
|
+
width: "100%",
|
|
7223
|
+
overflowX: "hidden",
|
|
7224
|
+
overflowY: "hidden",
|
|
7225
|
+
minWidth: 0
|
|
7226
|
+
},
|
|
7227
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
7228
|
+
"div",
|
|
7229
|
+
{
|
|
7230
|
+
className: cn("rounded-lg bg-card p-2 relative", className),
|
|
7231
|
+
style: { width: "100%", maxWidth: "100%", minWidth: 0 },
|
|
7232
|
+
children: [
|
|
7233
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7234
|
+
"div",
|
|
7235
|
+
{
|
|
7236
|
+
style: {
|
|
7237
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`,
|
|
7238
|
+
width: "100%",
|
|
7239
|
+
maxWidth: `${chartInnerWidth}px`,
|
|
7240
|
+
display: "flex",
|
|
7241
|
+
justifyContent: titlePosition === "center" ? "center" : titlePosition === "right" ? "flex-end" : "flex-start",
|
|
7242
|
+
alignItems: "center",
|
|
7243
|
+
marginTop: 4
|
|
7244
|
+
},
|
|
7245
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h3", { className: titleClassName, children: title })
|
|
7246
|
+
}
|
|
7247
|
+
),
|
|
7248
|
+
allKeys.length > 0 && (finalEnableHighlights || finalEnableShowOnly) && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
7249
|
+
"div",
|
|
7250
|
+
{
|
|
7251
|
+
className: "flex items-center w-full",
|
|
7252
|
+
style: {
|
|
7253
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`,
|
|
7254
|
+
width: "98%",
|
|
7255
|
+
display: "flex",
|
|
7256
|
+
alignItems: "center",
|
|
7257
|
+
gap: "0.5rem"
|
|
7258
|
+
},
|
|
7259
|
+
children: [
|
|
7260
|
+
finalEnableHighlights && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7261
|
+
Highlights_default,
|
|
7262
|
+
{
|
|
7263
|
+
allKeys,
|
|
7264
|
+
mapperConfig,
|
|
7265
|
+
finalColors,
|
|
7266
|
+
highlightedSeries,
|
|
7267
|
+
toggleHighlight,
|
|
7268
|
+
containerWidth: chartInnerWidth
|
|
7269
|
+
}
|
|
7270
|
+
),
|
|
7271
|
+
finalEnableShowOnly && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7272
|
+
ShowOnly_default,
|
|
7273
|
+
{
|
|
7274
|
+
showOnlyHighlighted,
|
|
7275
|
+
setShowOnlyHighlighted,
|
|
7276
|
+
highlightedSeriesSize: highlightedSeries.size,
|
|
7277
|
+
clearHighlights: () => setHighlightedSeries(/* @__PURE__ */ new Set())
|
|
7278
|
+
}
|
|
7279
|
+
),
|
|
7280
|
+
finalEnablePeriodsDropdown && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7281
|
+
"div",
|
|
7282
|
+
{
|
|
7283
|
+
style: {
|
|
7284
|
+
marginLeft: "auto",
|
|
7285
|
+
display: "flex",
|
|
7286
|
+
alignItems: "center"
|
|
7287
|
+
},
|
|
7288
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7289
|
+
PeriodsDropdown_default,
|
|
7290
|
+
{
|
|
7291
|
+
processedData,
|
|
7292
|
+
onOpenPeriod: openTooltipForPeriod,
|
|
7293
|
+
rightOffset: finalChartRightMargin,
|
|
7294
|
+
activePeriods
|
|
7295
|
+
}
|
|
7296
|
+
)
|
|
7297
|
+
}
|
|
7298
|
+
)
|
|
7299
|
+
]
|
|
7300
|
+
}
|
|
7301
|
+
),
|
|
7302
|
+
!(allKeys.length > 0 && (finalEnableHighlights || finalEnableShowOnly)) && finalEnablePeriodsDropdown && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7303
|
+
"div",
|
|
7304
|
+
{
|
|
7305
|
+
style: {
|
|
7306
|
+
paddingLeft: `${containerPaddingLeft + finalChartLeftMargin}px`,
|
|
7307
|
+
paddingRight: `${finalChartRightMargin}px`,
|
|
7308
|
+
width: "100%",
|
|
7309
|
+
maxWidth: `${chartInnerWidth}px`,
|
|
7310
|
+
display: "flex",
|
|
7311
|
+
justifyContent: "flex-end"
|
|
7312
|
+
},
|
|
7313
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7314
|
+
PeriodsDropdown_default,
|
|
7315
|
+
{
|
|
7316
|
+
processedData,
|
|
7317
|
+
onOpenPeriod: openTooltipForPeriod,
|
|
7318
|
+
rightOffset: finalChartRightMargin
|
|
7319
|
+
}
|
|
7320
|
+
)
|
|
7321
|
+
}
|
|
7322
|
+
),
|
|
7323
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_recharts.ResponsiveContainer, { width: "100%", height, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
7324
|
+
import_recharts.ComposedChart,
|
|
7325
|
+
{
|
|
7326
|
+
data: processedData,
|
|
7327
|
+
height,
|
|
7328
|
+
margin: {
|
|
7329
|
+
top: finalChartTopMargin,
|
|
7330
|
+
right: finalChartRightMargin,
|
|
7331
|
+
left: finalChartLeftMargin,
|
|
7332
|
+
bottom: finalChartBottomMargin
|
|
7333
|
+
},
|
|
7334
|
+
onClick: handleChartClick,
|
|
7335
|
+
children: [
|
|
7336
|
+
showGrid && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7337
|
+
import_recharts.CartesianGrid,
|
|
7338
|
+
{
|
|
7339
|
+
strokeDasharray: "3 3",
|
|
7340
|
+
stroke: gridColor || "hsl(var(--muted-foreground))",
|
|
7341
|
+
opacity: 0.5
|
|
7342
|
+
}
|
|
7343
|
+
),
|
|
7344
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7345
|
+
import_recharts.XAxis,
|
|
7346
|
+
{
|
|
7347
|
+
dataKey: xAxisConfig.dataKey,
|
|
7348
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7349
|
+
fontSize: 12,
|
|
7350
|
+
tickLine: false,
|
|
7351
|
+
axisLine: false,
|
|
7352
|
+
tickFormatter: xAxisConfig.formatter
|
|
7353
|
+
}
|
|
7354
|
+
),
|
|
7355
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7356
|
+
import_recharts.YAxis,
|
|
7357
|
+
{
|
|
7358
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7359
|
+
fontSize: 12,
|
|
7360
|
+
tickLine: false,
|
|
7361
|
+
axisLine: false,
|
|
7362
|
+
tickFormatter: (value) => Number(value).toLocaleString("pt-BR"),
|
|
7363
|
+
domain: [Math.min(minDataValue, 0), niceMax],
|
|
7364
|
+
tickCount: 6
|
|
7365
|
+
}
|
|
7366
|
+
),
|
|
7367
|
+
minDataValue < 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7368
|
+
import_recharts.ReferenceLine,
|
|
7369
|
+
{
|
|
7370
|
+
y: 0,
|
|
7371
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
7372
|
+
strokeWidth: 1,
|
|
7373
|
+
strokeDasharray: "4 4"
|
|
7374
|
+
}
|
|
7375
|
+
),
|
|
7376
|
+
showTooltip && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7377
|
+
import_recharts.Tooltip,
|
|
7378
|
+
{
|
|
7379
|
+
content: showTooltipTotal ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipWithTotal_default, { finalColors }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipSimple_default, { finalColors }),
|
|
7380
|
+
cursor: { fill: "hsl(var(--muted))", opacity: 0.1 }
|
|
7381
|
+
}
|
|
7382
|
+
),
|
|
7383
|
+
showLegend && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7384
|
+
import_recharts.Legend,
|
|
7385
|
+
{
|
|
7386
|
+
wrapperStyle: {
|
|
7387
|
+
color: "hsl(var(--foreground))",
|
|
7388
|
+
fontSize: "14px"
|
|
7389
|
+
}
|
|
7390
|
+
}
|
|
7391
|
+
),
|
|
7392
|
+
seriesOrder.map((s) => {
|
|
7393
|
+
const key = s.key;
|
|
7394
|
+
if (showOnlyHighlighted && !highlightedSeries.has(key))
|
|
7395
|
+
return null;
|
|
7396
|
+
const label = mapperConfig[key]?.label ?? labelMap?.[key] ?? formatFieldName(key);
|
|
7397
|
+
const color = finalColors[key];
|
|
7398
|
+
if (s.type === "bar") {
|
|
7399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7400
|
+
import_recharts.Bar,
|
|
7401
|
+
{
|
|
7402
|
+
dataKey: key,
|
|
7403
|
+
name: label,
|
|
7404
|
+
fill: color,
|
|
7405
|
+
radius: [4, 4, 0, 0],
|
|
7406
|
+
onClick: handleBarClick,
|
|
7407
|
+
style: {
|
|
7408
|
+
cursor: "pointer",
|
|
7409
|
+
opacity: highlightedSeries.size > 0 ? highlightedSeries.has(key) ? 1 : 0.25 : 1
|
|
7410
|
+
},
|
|
7411
|
+
activeBar: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7412
|
+
import_recharts.Rectangle,
|
|
7413
|
+
{
|
|
7414
|
+
fill: color,
|
|
7415
|
+
stroke: color,
|
|
7416
|
+
strokeWidth: 2,
|
|
7417
|
+
opacity: 0.8
|
|
7418
|
+
}
|
|
7419
|
+
),
|
|
7420
|
+
children: showLabels && highlightedSeries.size === 0 || highlightedSeries.has(key) ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7421
|
+
import_recharts.LabelList,
|
|
7422
|
+
{
|
|
7423
|
+
dataKey: key,
|
|
7424
|
+
position: "top",
|
|
7425
|
+
content: pillLabelRenderer_default(color, "filled"),
|
|
7426
|
+
offset: 8
|
|
7427
|
+
}
|
|
7428
|
+
) : null
|
|
7429
|
+
},
|
|
7430
|
+
`bar-${key}`
|
|
7431
|
+
);
|
|
7432
|
+
}
|
|
7433
|
+
if (s.type === "line") {
|
|
7434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7435
|
+
import_recharts.Line,
|
|
7436
|
+
{
|
|
7437
|
+
dataKey: key,
|
|
7438
|
+
name: label,
|
|
7439
|
+
stroke: color,
|
|
7440
|
+
strokeWidth: 2,
|
|
7441
|
+
dot: { r: 3 },
|
|
7442
|
+
activeDot: { r: 6 },
|
|
7443
|
+
onClick: handleSeriesClick,
|
|
7444
|
+
style: {
|
|
7445
|
+
cursor: "pointer",
|
|
7446
|
+
pointerEvents: "all",
|
|
7447
|
+
opacity: highlightedSeries.size > 0 ? highlightedSeries.has(key) ? 1 : 0.25 : 1
|
|
7448
|
+
},
|
|
7449
|
+
children: showLabels && highlightedSeries.size === 0 || highlightedSeries.has(key) ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7450
|
+
import_recharts.LabelList,
|
|
7451
|
+
{
|
|
7452
|
+
dataKey: key,
|
|
7453
|
+
position: "top",
|
|
7454
|
+
content: pillLabelRenderer_default(color, "filled"),
|
|
7455
|
+
offset: 14
|
|
7456
|
+
}
|
|
7457
|
+
) : null
|
|
7458
|
+
},
|
|
7459
|
+
`line-${key}`
|
|
7460
|
+
);
|
|
7461
|
+
}
|
|
7462
|
+
if (s.type === "area") {
|
|
7463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7464
|
+
import_recharts.Area,
|
|
7465
|
+
{
|
|
7466
|
+
dataKey: key,
|
|
7467
|
+
name: label,
|
|
7468
|
+
stroke: color,
|
|
7469
|
+
fill: color,
|
|
7470
|
+
fillOpacity: 0.35,
|
|
7471
|
+
strokeWidth: 2,
|
|
7472
|
+
onClick: handleSeriesClick,
|
|
7473
|
+
style: {
|
|
7474
|
+
cursor: "pointer",
|
|
7475
|
+
pointerEvents: "all",
|
|
7476
|
+
opacity: highlightedSeries.size > 0 ? highlightedSeries.has(key) ? 1 : 0.25 : 1
|
|
7477
|
+
},
|
|
7478
|
+
children: showLabels && highlightedSeries.size === 0 || highlightedSeries.has(key) ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7479
|
+
import_recharts.LabelList,
|
|
7480
|
+
{
|
|
7481
|
+
dataKey: key,
|
|
7482
|
+
position: "top",
|
|
7483
|
+
content: pillLabelRenderer_default(color, "soft"),
|
|
7484
|
+
offset: 12
|
|
7485
|
+
}
|
|
7486
|
+
) : null
|
|
7487
|
+
},
|
|
7488
|
+
`area-${key}`
|
|
7489
|
+
);
|
|
7490
|
+
}
|
|
7491
|
+
return null;
|
|
7492
|
+
})
|
|
7493
|
+
]
|
|
7494
|
+
}
|
|
7495
|
+
) }),
|
|
7496
|
+
enableDraggableTooltips && activeTooltips.map((tooltip) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7497
|
+
DraggableTooltip_default,
|
|
7498
|
+
{
|
|
7499
|
+
id: tooltip.id,
|
|
7500
|
+
data: adaptDataForTooltip(tooltip.data),
|
|
7501
|
+
position: tooltip.position,
|
|
7502
|
+
title,
|
|
7503
|
+
dataKeys: allKeys,
|
|
7504
|
+
finalColors,
|
|
7505
|
+
highlightedSeries,
|
|
7506
|
+
toggleHighlight,
|
|
7507
|
+
showOnlyHighlighted,
|
|
7508
|
+
onClose: (id) => setActiveTooltips((prev) => prev.filter((t) => t.id !== id)),
|
|
7509
|
+
onPositionChange: onTooltipPositionChange,
|
|
7510
|
+
periodLabel: "Per\xEDodo Selecionado",
|
|
7511
|
+
dataLabel: "Dados do Per\xEDodo",
|
|
7512
|
+
globalTooltipCount: activeTooltips.length,
|
|
7513
|
+
onCloseAll: () => window.dispatchEvent(new Event("closeAllTooltips")),
|
|
7514
|
+
closeAllButtonPosition: "top-center",
|
|
7515
|
+
closeAllButtonVariant: "floating"
|
|
7516
|
+
},
|
|
7517
|
+
tooltip.id
|
|
7518
|
+
)),
|
|
7519
|
+
enableDraggableTooltips && activeTooltips.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
7520
|
+
CloseAllButton_default,
|
|
7521
|
+
{
|
|
7522
|
+
count: activeTooltips.length,
|
|
7523
|
+
onCloseAll: () => window.dispatchEvent(new Event("closeAllTooltips")),
|
|
7524
|
+
position: "top-center",
|
|
7525
|
+
variant: "floating"
|
|
7526
|
+
}
|
|
7527
|
+
)
|
|
7528
|
+
]
|
|
7529
|
+
}
|
|
7530
|
+
)
|
|
7531
|
+
}
|
|
7532
|
+
);
|
|
7533
|
+
};
|
|
7534
|
+
var Chart_default = Chart;
|
|
7535
|
+
|
|
7536
|
+
// src/components/charts/BarChart.tsx
|
|
7537
|
+
var import_react36 = require("react");
|
|
7538
|
+
var import_recharts2 = require("recharts");
|
|
7539
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
7540
|
+
var DEFAULT_COLORS2 = ["#55af7d", "#8e68ff", "#2273e1"];
|
|
7541
|
+
var BarChart = ({
|
|
7542
|
+
data,
|
|
7543
|
+
className,
|
|
7544
|
+
height = 350,
|
|
7545
|
+
width = 900,
|
|
7546
|
+
colors: colors2 = DEFAULT_COLORS2,
|
|
7547
|
+
gridColor,
|
|
7548
|
+
showGrid = true,
|
|
7549
|
+
showTooltip = true,
|
|
7550
|
+
showLegend = true,
|
|
7551
|
+
title,
|
|
7552
|
+
titlePosition = "left",
|
|
7553
|
+
showLabels = false,
|
|
7554
|
+
xAxis,
|
|
7555
|
+
mapper,
|
|
7556
|
+
yAxis,
|
|
7557
|
+
labelMap,
|
|
7558
|
+
autoDetect = false,
|
|
7559
|
+
padding,
|
|
7560
|
+
margins,
|
|
7561
|
+
containerPaddingLeft,
|
|
7562
|
+
chartMargins
|
|
7563
|
+
}) => {
|
|
7564
|
+
const resolvedContainerPaddingLeft = resolveContainerPaddingLeft(
|
|
7565
|
+
padding,
|
|
7566
|
+
containerPaddingLeft,
|
|
7567
|
+
16
|
|
7568
|
+
);
|
|
7569
|
+
const smartConfig = (0, import_react36.useMemo)(() => {
|
|
7570
|
+
const providedMapper = yAxis ?? mapper;
|
|
7571
|
+
if (autoDetect === true || xAxis == null || providedMapper == null) {
|
|
7572
|
+
const detectedXAxis = detectXAxis(data);
|
|
7573
|
+
const detectedFields = detectDataFields(data, detectedXAxis);
|
|
7574
|
+
return {
|
|
7575
|
+
xAxisConfig: {
|
|
7576
|
+
dataKey: detectedXAxis,
|
|
7577
|
+
label: labelMap?.[detectedXAxis] ?? formatFieldName(detectedXAxis),
|
|
7578
|
+
autoLabel: true
|
|
7579
|
+
},
|
|
7580
|
+
mapperConfig: detectedFields.reduce((acc, field) => {
|
|
7581
|
+
acc[field] = {
|
|
7582
|
+
label: labelMap?.[field] ?? formatFieldName(field),
|
|
7583
|
+
type: "number",
|
|
7584
|
+
visible: true
|
|
7585
|
+
};
|
|
7586
|
+
return acc;
|
|
7587
|
+
}, {})
|
|
7588
|
+
};
|
|
7589
|
+
}
|
|
7590
|
+
const xAxisConfig2 = typeof xAxis === "string" ? { dataKey: xAxis, label: formatFieldName(xAxis), autoLabel: true } : xAxis;
|
|
7591
|
+
let mapperConfig2;
|
|
7592
|
+
if (Array.isArray(providedMapper)) {
|
|
7593
|
+
mapperConfig2 = providedMapper.reduce((acc, field) => {
|
|
7594
|
+
acc[field] = {
|
|
7595
|
+
label: labelMap?.[field] ?? formatFieldName(field),
|
|
7596
|
+
type: "auto",
|
|
7597
|
+
visible: true
|
|
7598
|
+
};
|
|
7599
|
+
return acc;
|
|
7600
|
+
}, {});
|
|
7601
|
+
} else {
|
|
7602
|
+
mapperConfig2 = Object.keys(providedMapper).reduce(
|
|
7603
|
+
(acc, key) => {
|
|
7604
|
+
acc[key] = {
|
|
7605
|
+
label: providedMapper[key]?.label ?? labelMap?.[key] ?? formatFieldName(key),
|
|
7606
|
+
type: "auto",
|
|
7607
|
+
visible: true,
|
|
7608
|
+
...providedMapper[key]
|
|
7609
|
+
// Sobrescreve com configurações do usuário
|
|
7610
|
+
};
|
|
7611
|
+
return acc;
|
|
7612
|
+
},
|
|
7613
|
+
{}
|
|
7614
|
+
);
|
|
7615
|
+
}
|
|
7616
|
+
return { xAxisConfig: xAxisConfig2, mapperConfig: mapperConfig2 };
|
|
7617
|
+
}, [data, xAxis, mapper, yAxis, autoDetect, labelMap]);
|
|
7618
|
+
const { xAxisConfig, mapperConfig } = smartConfig;
|
|
7619
|
+
const [activeTooltips, setActiveTooltips] = (0, import_react36.useState)([]);
|
|
7620
|
+
const [isDragging, setIsDragging] = (0, import_react36.useState)(null);
|
|
7621
|
+
const [dragOffset, setDragOffset] = (0, import_react36.useState)({
|
|
7622
|
+
x: 0,
|
|
7623
|
+
y: 0
|
|
7624
|
+
});
|
|
7625
|
+
const [globalTooltipCount, setGlobalTooltipCount] = (0, import_react36.useState)(0);
|
|
7626
|
+
const [alignmentGuides, setAlignmentGuides] = (0, import_react36.useState)([]);
|
|
7627
|
+
const processedData = data.map((item) => ({
|
|
7628
|
+
...item,
|
|
7629
|
+
name: String(item[xAxisConfig.dataKey] || "N/A")
|
|
7630
|
+
// Garantir propriedade 'name' para tooltip
|
|
7631
|
+
}));
|
|
7632
|
+
const generateColors = (dataKeys2) => {
|
|
7633
|
+
const colorMap = {};
|
|
7634
|
+
const allColors = generateAdditionalColors(colors2, dataKeys2.length);
|
|
7635
|
+
dataKeys2.forEach((key, index) => {
|
|
7636
|
+
colorMap[key] = allColors[index] || colors2[index % colors2.length];
|
|
7637
|
+
});
|
|
7638
|
+
return colorMap;
|
|
7639
|
+
};
|
|
7640
|
+
const dataKeys = Object.keys(mapperConfig);
|
|
7641
|
+
const finalColors = generateColors(dataKeys);
|
|
7642
|
+
const adaptDataForTooltip = (universalData) => {
|
|
7643
|
+
return {
|
|
7644
|
+
...universalData,
|
|
7645
|
+
name: String(universalData[xAxisConfig.dataKey] || "N/A")
|
|
7646
|
+
// Garantir que tem a propriedade 'name'
|
|
7647
|
+
};
|
|
7648
|
+
};
|
|
7649
|
+
const maxDataValue = (0, import_react36.useMemo)(() => {
|
|
7650
|
+
let max = 0;
|
|
7651
|
+
const keys = Object.keys(mapperConfig);
|
|
7652
|
+
for (const row of processedData) {
|
|
7653
|
+
const r = row;
|
|
7654
|
+
for (const key of keys) {
|
|
7655
|
+
const v = r[key];
|
|
7656
|
+
if (typeof v === "number" && Number.isFinite(v) && v > max)
|
|
7657
|
+
max = v;
|
|
7658
|
+
}
|
|
7659
|
+
}
|
|
7660
|
+
return max;
|
|
7661
|
+
}, [processedData, mapperConfig]);
|
|
7662
|
+
const niceMax = (0, import_react36.useMemo)(() => {
|
|
7663
|
+
let padding2 = 0.08;
|
|
7664
|
+
if (maxDataValue > 1e6) padding2 = 0.05;
|
|
7665
|
+
if (maxDataValue > 1e7) padding2 = 0.03;
|
|
7666
|
+
if (maxDataValue === 0) padding2 = 0.12;
|
|
7667
|
+
const padded = maxDataValue * (1 + padding2);
|
|
7668
|
+
return niceCeil(padded);
|
|
7669
|
+
}, [maxDataValue]);
|
|
7670
|
+
const handleBarClick = (data2, index, event) => {
|
|
7671
|
+
event.stopPropagation();
|
|
7672
|
+
const xAxisValue = data2[xAxisConfig.dataKey] || "N/A";
|
|
7673
|
+
const tooltipId = `${xAxisValue}`;
|
|
7674
|
+
const rect = event.target.getBoundingClientRect();
|
|
7675
|
+
const existingIndex = activeTooltips.findIndex(
|
|
7676
|
+
(tooltip) => tooltip.id === tooltipId
|
|
7677
|
+
);
|
|
7678
|
+
if (existingIndex !== -1) {
|
|
7679
|
+
setActiveTooltips(
|
|
7680
|
+
(prev) => prev.filter((tooltip) => tooltip.id !== tooltipId)
|
|
7681
|
+
);
|
|
7682
|
+
} else {
|
|
7683
|
+
const newTooltip = {
|
|
7684
|
+
id: tooltipId,
|
|
7685
|
+
data: data2,
|
|
7686
|
+
position: {
|
|
7687
|
+
top: rect.top - 10,
|
|
7688
|
+
// Posição fixa da viewport
|
|
7689
|
+
left: rect.right + 10
|
|
7690
|
+
// À direita da barra clicada
|
|
7691
|
+
}
|
|
7692
|
+
};
|
|
7693
|
+
setActiveTooltips((prev) => [...prev, newTooltip]);
|
|
7694
|
+
}
|
|
7695
|
+
};
|
|
7696
|
+
const handleChartClick = () => {
|
|
7697
|
+
setActiveTooltips([]);
|
|
7698
|
+
};
|
|
7699
|
+
const ALIGNMENT_THRESHOLD2 = 25;
|
|
7700
|
+
const GUIDE_THRESHOLD2 = 60;
|
|
7701
|
+
const STRONG_SNAP_THRESHOLD2 = 35;
|
|
7702
|
+
const PRECISION_SNAP_THRESHOLD2 = 8;
|
|
7703
|
+
const updateAlignmentGuides = (0, import_react36.useCallback)(
|
|
7704
|
+
(draggedTooltipId, currentPosition) => {
|
|
7705
|
+
if (!isDragging) return;
|
|
7706
|
+
const getAllTooltips = () => {
|
|
7707
|
+
const allTooltips2 = [];
|
|
7708
|
+
allTooltips2.push(...activeTooltips);
|
|
7709
|
+
const globalEvent = new CustomEvent("requestGlobalTooltips", {
|
|
7710
|
+
detail: { requesterId: draggedTooltipId, response: allTooltips2 }
|
|
7711
|
+
});
|
|
7712
|
+
window.dispatchEvent(globalEvent);
|
|
7713
|
+
return allTooltips2;
|
|
7714
|
+
};
|
|
7715
|
+
const allTooltips = getAllTooltips();
|
|
7716
|
+
const otherTooltips = allTooltips.filter(
|
|
7717
|
+
(t) => t.id !== draggedTooltipId
|
|
7718
|
+
);
|
|
7719
|
+
const guides = [];
|
|
7720
|
+
const tooltipDimensions = { width: 224, height: 120 };
|
|
7721
|
+
otherTooltips.forEach((tooltip) => {
|
|
7722
|
+
const topDiff = Math.abs(currentPosition.top - tooltip.position.top);
|
|
7723
|
+
if (topDiff <= GUIDE_THRESHOLD2) {
|
|
7724
|
+
guides.push({
|
|
7725
|
+
type: "horizontal",
|
|
7726
|
+
position: tooltip.position.top,
|
|
7727
|
+
visible: true,
|
|
7728
|
+
sourceTooltip: {
|
|
7729
|
+
top: currentPosition.top,
|
|
7730
|
+
left: currentPosition.left,
|
|
7731
|
+
width: tooltipDimensions.width,
|
|
7732
|
+
height: tooltipDimensions.height
|
|
7733
|
+
},
|
|
7734
|
+
targetTooltip: {
|
|
7735
|
+
top: tooltip.position.top,
|
|
7736
|
+
left: tooltip.position.left,
|
|
7737
|
+
width: tooltipDimensions.width,
|
|
7738
|
+
height: tooltipDimensions.height
|
|
7739
|
+
}
|
|
7740
|
+
});
|
|
7741
|
+
}
|
|
7742
|
+
const leftDiff = Math.abs(currentPosition.left - tooltip.position.left);
|
|
7743
|
+
if (leftDiff <= GUIDE_THRESHOLD2) {
|
|
7744
|
+
guides.push({
|
|
7745
|
+
type: "vertical",
|
|
7746
|
+
position: tooltip.position.left,
|
|
7747
|
+
visible: true,
|
|
7748
|
+
sourceTooltip: {
|
|
7749
|
+
top: currentPosition.top,
|
|
7750
|
+
left: currentPosition.left,
|
|
7751
|
+
width: tooltipDimensions.width,
|
|
7752
|
+
height: tooltipDimensions.height
|
|
7753
|
+
},
|
|
7754
|
+
targetTooltip: {
|
|
7755
|
+
top: tooltip.position.top,
|
|
7756
|
+
left: tooltip.position.left,
|
|
7757
|
+
width: tooltipDimensions.width,
|
|
7758
|
+
height: tooltipDimensions.height
|
|
7759
|
+
}
|
|
7760
|
+
});
|
|
7761
|
+
}
|
|
7762
|
+
});
|
|
7763
|
+
setAlignmentGuides(guides);
|
|
7764
|
+
},
|
|
7765
|
+
[isDragging, activeTooltips]
|
|
7766
|
+
);
|
|
7767
|
+
const snapToGuides = (0, import_react36.useCallback)(
|
|
7768
|
+
(position) => {
|
|
7769
|
+
const snappedPosition = { ...position };
|
|
7770
|
+
let hasSnapped = false;
|
|
7771
|
+
alignmentGuides.forEach((guide) => {
|
|
7772
|
+
if (guide.type === "horizontal") {
|
|
7773
|
+
const diff = Math.abs(position.top - guide.position);
|
|
7774
|
+
if (diff <= PRECISION_SNAP_THRESHOLD2) {
|
|
7775
|
+
snappedPosition.top = guide.position;
|
|
7776
|
+
hasSnapped = true;
|
|
7777
|
+
}
|
|
7778
|
+
} else if (guide.type === "vertical") {
|
|
7779
|
+
const diff = Math.abs(position.left - guide.position);
|
|
7780
|
+
if (diff <= PRECISION_SNAP_THRESHOLD2) {
|
|
7781
|
+
snappedPosition.left = guide.position;
|
|
7782
|
+
hasSnapped = true;
|
|
7783
|
+
}
|
|
7784
|
+
}
|
|
7785
|
+
});
|
|
7786
|
+
if (!hasSnapped) {
|
|
7787
|
+
alignmentGuides.forEach((guide) => {
|
|
7788
|
+
if (guide.type === "horizontal") {
|
|
7789
|
+
const diff = Math.abs(position.top - guide.position);
|
|
7790
|
+
if (diff <= STRONG_SNAP_THRESHOLD2) {
|
|
7791
|
+
snappedPosition.top = guide.position;
|
|
7792
|
+
}
|
|
7793
|
+
} else if (guide.type === "vertical") {
|
|
7794
|
+
const diff = Math.abs(position.left - guide.position);
|
|
7795
|
+
if (diff <= STRONG_SNAP_THRESHOLD2) {
|
|
7796
|
+
snappedPosition.left = guide.position;
|
|
7797
|
+
}
|
|
7798
|
+
}
|
|
7799
|
+
});
|
|
7800
|
+
}
|
|
7801
|
+
alignmentGuides.forEach((guide) => {
|
|
7802
|
+
if (guide.type === "horizontal") {
|
|
7803
|
+
const diff = Math.abs(position.top - guide.position);
|
|
7804
|
+
if (diff <= ALIGNMENT_THRESHOLD2 && snappedPosition.top === position.top) {
|
|
7805
|
+
snappedPosition.top = guide.position;
|
|
7806
|
+
}
|
|
7807
|
+
} else if (guide.type === "vertical") {
|
|
7808
|
+
const diff = Math.abs(position.left - guide.position);
|
|
7809
|
+
if (diff <= ALIGNMENT_THRESHOLD2 && snappedPosition.left === position.left) {
|
|
7810
|
+
snappedPosition.left = guide.position;
|
|
7811
|
+
}
|
|
7812
|
+
}
|
|
7813
|
+
});
|
|
7814
|
+
return snappedPosition;
|
|
7815
|
+
},
|
|
7816
|
+
[alignmentGuides]
|
|
7817
|
+
);
|
|
7818
|
+
const handleMouseDown = (e, tooltipId) => {
|
|
7819
|
+
e.preventDefault();
|
|
7820
|
+
e.stopPropagation();
|
|
7821
|
+
const tooltip = activeTooltips.find((t) => t.id === tooltipId);
|
|
7822
|
+
if (!tooltip) return;
|
|
7823
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
7824
|
+
const offsetX = e.clientX - rect.left;
|
|
7825
|
+
const offsetY = e.clientY - rect.top;
|
|
7826
|
+
setIsDragging(tooltipId);
|
|
7827
|
+
setDragOffset({ x: offsetX, y: offsetY });
|
|
7828
|
+
};
|
|
7829
|
+
(0, import_react36.useEffect)(() => {
|
|
7830
|
+
let rafId;
|
|
7831
|
+
let lastMousePosition = { x: 0, y: 0 };
|
|
7832
|
+
const handleGlobalMouseMove = (e) => {
|
|
7833
|
+
if (!isDragging) return;
|
|
7834
|
+
lastMousePosition = { x: e.clientX, y: e.clientY };
|
|
7835
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
7836
|
+
rafId = requestAnimationFrame(() => {
|
|
7837
|
+
const newLeft = lastMousePosition.x - dragOffset.x;
|
|
7838
|
+
const newTop = lastMousePosition.y - dragOffset.y;
|
|
7839
|
+
const rawPosition = {
|
|
7840
|
+
top: Math.max(0, Math.min(newTop, window.innerHeight - 200)),
|
|
7841
|
+
left: Math.max(0, Math.min(newLeft, window.innerWidth - 250))
|
|
7842
|
+
};
|
|
7843
|
+
updateAlignmentGuides(isDragging, rawPosition);
|
|
7844
|
+
const snappedPosition = snapToGuides(rawPosition);
|
|
7845
|
+
setActiveTooltips(
|
|
7846
|
+
(prev) => prev.map((tooltip) => {
|
|
7847
|
+
if (tooltip.id === isDragging) {
|
|
7848
|
+
return {
|
|
7849
|
+
...tooltip,
|
|
7850
|
+
position: snappedPosition
|
|
7851
|
+
};
|
|
7852
|
+
}
|
|
7853
|
+
return tooltip;
|
|
7854
|
+
})
|
|
7855
|
+
);
|
|
7856
|
+
});
|
|
6663
7857
|
};
|
|
6664
|
-
|
|
7858
|
+
const handleGlobalMouseUp = () => {
|
|
7859
|
+
if (isDragging) {
|
|
7860
|
+
setIsDragging(null);
|
|
7861
|
+
setAlignmentGuides([]);
|
|
7862
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
7863
|
+
}
|
|
7864
|
+
};
|
|
7865
|
+
if (isDragging) {
|
|
7866
|
+
document.addEventListener("mousemove", handleGlobalMouseMove, {
|
|
7867
|
+
passive: true
|
|
7868
|
+
});
|
|
7869
|
+
document.addEventListener("mouseup", handleGlobalMouseUp);
|
|
7870
|
+
document.body.style.cursor = "grabbing";
|
|
7871
|
+
document.body.style.userSelect = "none";
|
|
7872
|
+
}
|
|
7873
|
+
return () => {
|
|
7874
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
7875
|
+
document.removeEventListener("mousemove", handleGlobalMouseMove);
|
|
7876
|
+
document.removeEventListener("mouseup", handleGlobalMouseUp);
|
|
7877
|
+
document.body.style.cursor = "";
|
|
7878
|
+
document.body.style.userSelect = "";
|
|
7879
|
+
};
|
|
7880
|
+
}, [
|
|
7881
|
+
isDragging,
|
|
7882
|
+
dragOffset,
|
|
7883
|
+
alignmentGuides,
|
|
7884
|
+
updateAlignmentGuides,
|
|
7885
|
+
snapToGuides
|
|
7886
|
+
]);
|
|
7887
|
+
(0, import_react36.useEffect)(() => {
|
|
7888
|
+
const handleCloseAllTooltips = () => {
|
|
7889
|
+
setActiveTooltips([]);
|
|
7890
|
+
setGlobalTooltipCount(0);
|
|
7891
|
+
};
|
|
7892
|
+
window.addEventListener("closeAllTooltips", handleCloseAllTooltips);
|
|
7893
|
+
return () => {
|
|
7894
|
+
window.removeEventListener("closeAllTooltips", handleCloseAllTooltips);
|
|
7895
|
+
};
|
|
7896
|
+
}, []);
|
|
7897
|
+
(0, import_react36.useEffect)(() => {
|
|
7898
|
+
const handleTooltipCountRequest = () => {
|
|
7899
|
+
window.dispatchEvent(
|
|
7900
|
+
new CustomEvent("tooltipCountResponse", {
|
|
7901
|
+
detail: { count: activeTooltips.length }
|
|
7902
|
+
})
|
|
7903
|
+
);
|
|
7904
|
+
};
|
|
7905
|
+
const handleGlobalTooltipsRequest = (event) => {
|
|
7906
|
+
const { detail } = event;
|
|
7907
|
+
if (detail && detail.response && detail.requesterId) {
|
|
7908
|
+
activeTooltips.forEach((tooltip) => {
|
|
7909
|
+
if (!detail.response.find(
|
|
7910
|
+
(t) => t.id === tooltip.id
|
|
7911
|
+
)) {
|
|
7912
|
+
detail.response.push({
|
|
7913
|
+
id: tooltip.id,
|
|
7914
|
+
position: tooltip.position
|
|
7915
|
+
});
|
|
7916
|
+
}
|
|
7917
|
+
});
|
|
7918
|
+
}
|
|
7919
|
+
};
|
|
7920
|
+
window.addEventListener("requestTooltipCount", handleTooltipCountRequest);
|
|
7921
|
+
window.addEventListener(
|
|
7922
|
+
"requestGlobalTooltips",
|
|
7923
|
+
handleGlobalTooltipsRequest
|
|
7924
|
+
);
|
|
7925
|
+
return () => {
|
|
7926
|
+
window.removeEventListener(
|
|
7927
|
+
"requestTooltipCount",
|
|
7928
|
+
handleTooltipCountRequest
|
|
7929
|
+
);
|
|
7930
|
+
window.removeEventListener(
|
|
7931
|
+
"requestGlobalTooltips",
|
|
7932
|
+
handleGlobalTooltipsRequest
|
|
7933
|
+
);
|
|
7934
|
+
};
|
|
7935
|
+
}, [activeTooltips]);
|
|
7936
|
+
(0, import_react36.useEffect)(() => {
|
|
7937
|
+
if (isDragging) return;
|
|
7938
|
+
let totalCount = 0;
|
|
7939
|
+
const handleCountResponse = (event) => {
|
|
7940
|
+
const customEvent = event;
|
|
7941
|
+
totalCount += customEvent.detail.count;
|
|
7942
|
+
};
|
|
7943
|
+
window.addEventListener("tooltipCountResponse", handleCountResponse);
|
|
7944
|
+
window.dispatchEvent(new CustomEvent("requestTooltipCount"));
|
|
7945
|
+
const timeoutId = setTimeout(() => {
|
|
7946
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
7947
|
+
setGlobalTooltipCount(totalCount);
|
|
7948
|
+
}, 5);
|
|
7949
|
+
return () => {
|
|
7950
|
+
clearTimeout(timeoutId);
|
|
7951
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
7952
|
+
};
|
|
7953
|
+
}, [activeTooltips.length, isDragging]);
|
|
7954
|
+
const CustomTooltip = ({
|
|
7955
|
+
active,
|
|
7956
|
+
payload,
|
|
7957
|
+
label
|
|
7958
|
+
}) => {
|
|
7959
|
+
if (!active || !payload) return null;
|
|
7960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "bg-card border border-border rounded-lg p-3 shadow-lg", children: [
|
|
7961
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "font-medium text-foreground mb-2", children: label }),
|
|
7962
|
+
payload.map(
|
|
7963
|
+
(entry, index) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
7964
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
7965
|
+
"div",
|
|
7966
|
+
{
|
|
7967
|
+
className: "w-3 h-3 rounded-sm",
|
|
7968
|
+
style: { backgroundColor: entry.color }
|
|
7969
|
+
}
|
|
7970
|
+
),
|
|
7971
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
7972
|
+
entry.name,
|
|
7973
|
+
":"
|
|
7974
|
+
] }),
|
|
7975
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "text-foreground font-medium", children: entry.value?.toLocaleString("pt-BR") })
|
|
7976
|
+
] }, index)
|
|
7977
|
+
),
|
|
7978
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "text-xs text-muted-foreground mt-1", children: "Clique para fixar este tooltip" })
|
|
7979
|
+
] });
|
|
6665
7980
|
};
|
|
6666
|
-
const
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
}
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
7981
|
+
const getTitleClassName = (position) => {
|
|
7982
|
+
const baseClasses = "text-xl font-semibold text-foreground mb-3";
|
|
7983
|
+
switch (position) {
|
|
7984
|
+
case "center":
|
|
7985
|
+
return `${baseClasses} text-center`;
|
|
7986
|
+
case "right":
|
|
7987
|
+
return `${baseClasses} text-right`;
|
|
7988
|
+
default:
|
|
7989
|
+
return `${baseClasses} text-left`;
|
|
7990
|
+
}
|
|
7991
|
+
};
|
|
7992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
7993
|
+
"div",
|
|
7994
|
+
{
|
|
7995
|
+
className: cn("rounded-lg bg-card p-4 relative", className),
|
|
7996
|
+
style: {
|
|
7997
|
+
width: typeof width === "number" ? `${width + 32}px` : "fit-content",
|
|
7998
|
+
maxWidth: "100%"
|
|
7999
|
+
},
|
|
8000
|
+
children: [
|
|
8001
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { style: { paddingLeft: `${resolvedContainerPaddingLeft}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h3", { className: getTitleClassName(titlePosition), children: title }) }),
|
|
8002
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
8003
|
+
import_recharts2.BarChart,
|
|
8004
|
+
{
|
|
8005
|
+
data: processedData,
|
|
8006
|
+
width: typeof width === "number" ? width : 900,
|
|
8007
|
+
height,
|
|
8008
|
+
margin: resolveChartMargins(margins, chartMargins, showLabels),
|
|
8009
|
+
onClick: handleChartClick,
|
|
8010
|
+
children: [
|
|
8011
|
+
showGrid && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8012
|
+
import_recharts2.CartesianGrid,
|
|
8013
|
+
{
|
|
8014
|
+
strokeDasharray: "3 3",
|
|
8015
|
+
stroke: gridColor || "hsl(var(--muted-foreground))",
|
|
8016
|
+
opacity: 0.5
|
|
8017
|
+
}
|
|
8018
|
+
),
|
|
8019
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8020
|
+
import_recharts2.XAxis,
|
|
8021
|
+
{
|
|
8022
|
+
dataKey: xAxisConfig.dataKey,
|
|
8023
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
8024
|
+
fontSize: 12,
|
|
8025
|
+
tickLine: false,
|
|
8026
|
+
axisLine: false,
|
|
8027
|
+
tickFormatter: xAxisConfig.formatter
|
|
8028
|
+
}
|
|
8029
|
+
),
|
|
8030
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8031
|
+
import_recharts2.YAxis,
|
|
8032
|
+
{
|
|
8033
|
+
stroke: "hsl(var(--muted-foreground))",
|
|
8034
|
+
fontSize: 12,
|
|
8035
|
+
tickLine: false,
|
|
8036
|
+
axisLine: false,
|
|
8037
|
+
tickFormatter: (value) => value.toLocaleString("pt-BR"),
|
|
8038
|
+
domain: [0, niceMax],
|
|
8039
|
+
tickCount: 6
|
|
8040
|
+
}
|
|
8041
|
+
),
|
|
8042
|
+
showTooltip && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8043
|
+
import_recharts2.Tooltip,
|
|
8044
|
+
{
|
|
8045
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CustomTooltip, {}),
|
|
8046
|
+
cursor: { fill: "hsl(var(--muted))", opacity: 0.1 }
|
|
8047
|
+
}
|
|
8048
|
+
),
|
|
8049
|
+
showLegend && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8050
|
+
import_recharts2.Legend,
|
|
8051
|
+
{
|
|
8052
|
+
wrapperStyle: {
|
|
8053
|
+
color: "hsl(var(--foreground))",
|
|
8054
|
+
fontSize: "14px"
|
|
8055
|
+
}
|
|
8056
|
+
}
|
|
8057
|
+
),
|
|
8058
|
+
dataKeys.map((key) => {
|
|
8059
|
+
const fieldConfig = mapperConfig[key];
|
|
8060
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8061
|
+
import_recharts2.Bar,
|
|
8062
|
+
{
|
|
8063
|
+
dataKey: key,
|
|
8064
|
+
name: fieldConfig?.label || key,
|
|
8065
|
+
fill: fieldConfig?.color || finalColors[key],
|
|
8066
|
+
radius: [4, 4, 0, 0],
|
|
8067
|
+
onClick: handleBarClick,
|
|
8068
|
+
style: { cursor: "pointer" },
|
|
8069
|
+
activeBar: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8070
|
+
import_recharts2.Rectangle,
|
|
8071
|
+
{
|
|
8072
|
+
fill: finalColors[key],
|
|
8073
|
+
stroke: finalColors[key],
|
|
8074
|
+
strokeWidth: 2,
|
|
8075
|
+
opacity: 0.8
|
|
8076
|
+
}
|
|
8077
|
+
),
|
|
8078
|
+
children: showLabels && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8079
|
+
import_recharts2.LabelList,
|
|
8080
|
+
{
|
|
8081
|
+
dataKey: key,
|
|
8082
|
+
position: "top",
|
|
8083
|
+
content: pillLabelRenderer_default(
|
|
8084
|
+
finalColors[key] || "#000",
|
|
8085
|
+
"filled"
|
|
8086
|
+
)
|
|
8087
|
+
}
|
|
8088
|
+
)
|
|
8089
|
+
},
|
|
8090
|
+
key
|
|
8091
|
+
);
|
|
8092
|
+
})
|
|
8093
|
+
]
|
|
8094
|
+
}
|
|
8095
|
+
),
|
|
8096
|
+
alignmentGuides.map((guide, index) => {
|
|
8097
|
+
const isHorizontal = guide.type === "horizontal";
|
|
8098
|
+
const color = isHorizontal ? "#3b82f6" : "#ef4444";
|
|
8099
|
+
const startX = isHorizontal ? Math.min(
|
|
8100
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
8101
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
8102
|
+
) : guide.sourceTooltip.left + (isHorizontal ? 0 : guide.sourceTooltip.width / 2);
|
|
8103
|
+
const endX = isHorizontal ? Math.max(
|
|
8104
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
8105
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
8106
|
+
) : guide.targetTooltip.left + (isHorizontal ? 0 : guide.targetTooltip.width / 2);
|
|
8107
|
+
const startY = isHorizontal ? guide.sourceTooltip.top + (isHorizontal ? guide.sourceTooltip.height / 2 : 0) : Math.min(
|
|
8108
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
8109
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
8110
|
+
);
|
|
8111
|
+
const endY = isHorizontal ? guide.targetTooltip.top + (isHorizontal ? guide.targetTooltip.height / 2 : 0) : Math.max(
|
|
8112
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
8113
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
8114
|
+
);
|
|
8115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { children: [
|
|
8116
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8117
|
+
"div",
|
|
8118
|
+
{
|
|
8119
|
+
className: "fixed pointer-events-none z-30",
|
|
8120
|
+
style: {
|
|
8121
|
+
left: startX,
|
|
8122
|
+
top: startY,
|
|
8123
|
+
width: isHorizontal ? endX - startX : "2px",
|
|
8124
|
+
height: isHorizontal ? "2px" : endY - startY,
|
|
8125
|
+
backgroundColor: color,
|
|
8126
|
+
boxShadow: `0 0 8px ${color}60`,
|
|
8127
|
+
opacity: 0.9,
|
|
8128
|
+
borderStyle: "dashed",
|
|
8129
|
+
borderWidth: "1px",
|
|
8130
|
+
borderColor: color,
|
|
8131
|
+
transform: "translateZ(0)"
|
|
8132
|
+
}
|
|
8133
|
+
}
|
|
8134
|
+
),
|
|
8135
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8136
|
+
"div",
|
|
8137
|
+
{
|
|
8138
|
+
className: "fixed pointer-events-none z-31",
|
|
8139
|
+
style: {
|
|
8140
|
+
left: guide.sourceTooltip.left + guide.sourceTooltip.width / 2 - 4,
|
|
8141
|
+
top: guide.sourceTooltip.top + guide.sourceTooltip.height / 2 - 4,
|
|
8142
|
+
width: "8px",
|
|
8143
|
+
height: "8px",
|
|
8144
|
+
backgroundColor: color,
|
|
8145
|
+
borderRadius: "50%",
|
|
8146
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
8147
|
+
opacity: 0.8
|
|
8148
|
+
}
|
|
8149
|
+
}
|
|
8150
|
+
),
|
|
8151
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8152
|
+
"div",
|
|
8153
|
+
{
|
|
8154
|
+
className: "fixed pointer-events-none z-31",
|
|
8155
|
+
style: {
|
|
8156
|
+
left: guide.targetTooltip.left + guide.targetTooltip.width / 2 - 4,
|
|
8157
|
+
top: guide.targetTooltip.top + guide.targetTooltip.height / 2 - 4,
|
|
8158
|
+
width: "8px",
|
|
8159
|
+
height: "8px",
|
|
8160
|
+
backgroundColor: color,
|
|
8161
|
+
borderRadius: "50%",
|
|
8162
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
8163
|
+
opacity: 0.8
|
|
8164
|
+
}
|
|
8165
|
+
}
|
|
8166
|
+
)
|
|
8167
|
+
] }, index);
|
|
8168
|
+
}),
|
|
8169
|
+
activeTooltips.map((tooltip, index) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
8170
|
+
DraggableTooltip_default,
|
|
8171
|
+
{
|
|
8172
|
+
id: tooltip.id,
|
|
8173
|
+
data: adaptDataForTooltip(tooltip.data),
|
|
8174
|
+
position: tooltip.position,
|
|
8175
|
+
isDragging: isDragging === tooltip.id,
|
|
8176
|
+
title,
|
|
8177
|
+
dataKeys,
|
|
8178
|
+
finalColors,
|
|
8179
|
+
onMouseDown: (id, e) => handleMouseDown(e, id),
|
|
8180
|
+
onClose: (id) => {
|
|
8181
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== id));
|
|
8182
|
+
},
|
|
8183
|
+
periodLabel: "Per\xEDodo Selecionado",
|
|
8184
|
+
dataLabel: "Dados do Per\xEDodo",
|
|
8185
|
+
showCloseAllButton: index === 0,
|
|
8186
|
+
globalTooltipCount,
|
|
8187
|
+
onCloseAll: () => {
|
|
8188
|
+
window.dispatchEvent(new Event("closeAllTooltips"));
|
|
8189
|
+
},
|
|
8190
|
+
closeAllButtonPosition: "top-center",
|
|
8191
|
+
closeAllButtonVariant: "floating"
|
|
8192
|
+
},
|
|
8193
|
+
tooltip.id
|
|
8194
|
+
))
|
|
8195
|
+
]
|
|
8196
|
+
}
|
|
8197
|
+
);
|
|
6723
8198
|
};
|
|
6724
|
-
var
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
8199
|
+
var BarChart_default = BarChart;
|
|
8200
|
+
|
|
8201
|
+
// src/components/charts/LineChart.tsx
|
|
8202
|
+
var import_react37 = require("react");
|
|
8203
|
+
var import_recharts3 = require("recharts");
|
|
8204
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
8205
|
+
var defaultData = [
|
|
8206
|
+
{ name: "A", value: 100 },
|
|
8207
|
+
{ name: "B", value: 200 },
|
|
8208
|
+
{ name: "C", value: 150 }
|
|
8209
|
+
];
|
|
8210
|
+
var DEFAULT_COLORS3 = ["#55af7d", "#8e68ff", "#2273e1"];
|
|
8211
|
+
var CustomLineChart = ({
|
|
8212
|
+
data = defaultData,
|
|
8213
|
+
className,
|
|
8214
|
+
height = 300,
|
|
8215
|
+
width = "100%",
|
|
8216
|
+
colors: colors2 = DEFAULT_COLORS3,
|
|
8217
|
+
gridColor,
|
|
8218
|
+
showGrid = true,
|
|
8219
|
+
showTooltip = true,
|
|
8220
|
+
showLegend = true,
|
|
8221
|
+
title,
|
|
8222
|
+
titlePosition = "left",
|
|
8223
|
+
strokeWidth = 2,
|
|
8224
|
+
showDots = true,
|
|
8225
|
+
showLabels = false,
|
|
8226
|
+
padding,
|
|
8227
|
+
margins,
|
|
8228
|
+
containerPaddingLeft,
|
|
8229
|
+
chartMargins
|
|
8230
|
+
}) => {
|
|
8231
|
+
const resolvedContainerPaddingLeft = resolveContainerPaddingLeft(
|
|
8232
|
+
padding,
|
|
8233
|
+
containerPaddingLeft,
|
|
8234
|
+
16
|
|
8235
|
+
);
|
|
8236
|
+
const [activeTooltips, setActiveTooltips] = (0, import_react37.useState)([]);
|
|
8237
|
+
const [isDragging, setIsDragging] = (0, import_react37.useState)(null);
|
|
8238
|
+
const [dragOffset, setDragOffset] = (0, import_react37.useState)({
|
|
8239
|
+
x: 0,
|
|
8240
|
+
y: 0
|
|
8241
|
+
});
|
|
8242
|
+
const [globalTooltipCount, setGlobalTooltipCount] = (0, import_react37.useState)(0);
|
|
8243
|
+
const [alignmentGuides, setAlignmentGuides] = (0, import_react37.useState)([]);
|
|
8244
|
+
const generateColors = (dataKeys2) => {
|
|
8245
|
+
const colorMap = {};
|
|
8246
|
+
const allColors = generateAdditionalColors(colors2, dataKeys2.length);
|
|
8247
|
+
dataKeys2.forEach((key, index) => {
|
|
8248
|
+
colorMap[key] = allColors[index] || colors2[index % colors2.length];
|
|
8249
|
+
});
|
|
8250
|
+
return colorMap;
|
|
8251
|
+
};
|
|
8252
|
+
const dataKeys = (0, import_react37.useMemo)(
|
|
8253
|
+
() => data.length > 0 ? Object.keys(data[0]).filter((key) => key !== "name") : [],
|
|
8254
|
+
[data]
|
|
8255
|
+
);
|
|
8256
|
+
const finalColors = generateColors(dataKeys);
|
|
8257
|
+
const maxDataValue = (0, import_react37.useMemo)(() => {
|
|
8258
|
+
let max = 0;
|
|
8259
|
+
for (const row of data) {
|
|
8260
|
+
const r = row;
|
|
8261
|
+
for (const key of dataKeys) {
|
|
8262
|
+
const v = r[key];
|
|
8263
|
+
if (typeof v === "number" && Number.isFinite(v) && v > max)
|
|
8264
|
+
max = v;
|
|
8265
|
+
}
|
|
8266
|
+
}
|
|
8267
|
+
return max;
|
|
8268
|
+
}, [data, dataKeys]);
|
|
8269
|
+
const niceMax = (0, import_react37.useMemo)(() => {
|
|
8270
|
+
let padding2 = 0.08;
|
|
8271
|
+
if (maxDataValue > 1e6) padding2 = 0.05;
|
|
8272
|
+
if (maxDataValue > 1e7) padding2 = 0.03;
|
|
8273
|
+
if (maxDataValue === 0) padding2 = 0.12;
|
|
8274
|
+
const padded = maxDataValue * (1 + padding2);
|
|
8275
|
+
return niceCeil(padded);
|
|
8276
|
+
}, [maxDataValue]);
|
|
8277
|
+
const ClickableDot = (props) => {
|
|
8278
|
+
const { cx, cy, payload, dataKey } = props;
|
|
8279
|
+
const handleDotClick = (e) => {
|
|
8280
|
+
e.stopPropagation();
|
|
8281
|
+
if (!payload || !cx || !cy) return;
|
|
8282
|
+
const tooltipId = `${payload.name}`;
|
|
8283
|
+
const existingIndex = activeTooltips.findIndex(
|
|
8284
|
+
(tooltip) => tooltip.id === tooltipId
|
|
8285
|
+
);
|
|
8286
|
+
if (existingIndex !== -1) {
|
|
8287
|
+
setActiveTooltips(
|
|
8288
|
+
(prev) => prev.filter((tooltip) => tooltip.id !== tooltipId)
|
|
8289
|
+
);
|
|
8290
|
+
} else {
|
|
8291
|
+
const newTooltip = {
|
|
8292
|
+
id: tooltipId,
|
|
8293
|
+
data: payload,
|
|
8294
|
+
position: {
|
|
8295
|
+
top: cy - 50,
|
|
8296
|
+
// Posição relativa ao SVG
|
|
8297
|
+
left: cx - 100
|
|
8298
|
+
}
|
|
8299
|
+
};
|
|
8300
|
+
setActiveTooltips((prev) => [...prev, newTooltip]);
|
|
8301
|
+
}
|
|
8302
|
+
};
|
|
8303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8304
|
+
"circle",
|
|
8305
|
+
{
|
|
8306
|
+
cx,
|
|
8307
|
+
cy,
|
|
8308
|
+
r: 6,
|
|
8309
|
+
fill: finalColors[dataKey || ""] || colors2[0],
|
|
8310
|
+
stroke: finalColors[dataKey || ""] || colors2[0],
|
|
8311
|
+
strokeWidth: 2,
|
|
8312
|
+
style: { cursor: "pointer" },
|
|
8313
|
+
onClick: handleDotClick
|
|
8314
|
+
}
|
|
8315
|
+
);
|
|
8316
|
+
};
|
|
8317
|
+
const handleChartClick = (e) => {
|
|
8318
|
+
if (e && e.activePayload && e.activePayload.length > 0) {
|
|
8319
|
+
const clickedData = e.activePayload[0].payload;
|
|
8320
|
+
const tooltipId = `${clickedData.name}`;
|
|
8321
|
+
const existingIndex = activeTooltips.findIndex(
|
|
8322
|
+
(tooltip) => tooltip.id === tooltipId
|
|
8323
|
+
);
|
|
8324
|
+
if (existingIndex !== -1) {
|
|
8325
|
+
setActiveTooltips(
|
|
8326
|
+
(prev) => prev.filter((tooltip) => tooltip.id !== tooltipId)
|
|
8327
|
+
);
|
|
8328
|
+
} else {
|
|
8329
|
+
const newTooltip = {
|
|
8330
|
+
id: tooltipId,
|
|
8331
|
+
data: clickedData,
|
|
8332
|
+
position: {
|
|
8333
|
+
top: (e.chartY || 100) - 10,
|
|
8334
|
+
left: (e.chartX || 100) - 100
|
|
8335
|
+
}
|
|
8336
|
+
};
|
|
8337
|
+
setActiveTooltips((prev) => [...prev, newTooltip]);
|
|
8338
|
+
}
|
|
8339
|
+
} else {
|
|
8340
|
+
}
|
|
8341
|
+
};
|
|
8342
|
+
const handleChartBackgroundClick = () => {
|
|
8343
|
+
setActiveTooltips([]);
|
|
8344
|
+
};
|
|
8345
|
+
const handleCloseAllTooltips = (0, import_react37.useCallback)(() => {
|
|
8346
|
+
window.dispatchEvent(new CustomEvent("closeAllTooltips"));
|
|
8347
|
+
}, []);
|
|
8348
|
+
const updateAlignmentGuides = (0, import_react37.useCallback)(
|
|
8349
|
+
(draggedTooltipId, draggedPosition) => {
|
|
8350
|
+
const SNAP_THRESHOLD = 15;
|
|
8351
|
+
const draggedTooltip = activeTooltips.find(
|
|
8352
|
+
(t) => t.id === draggedTooltipId
|
|
8353
|
+
);
|
|
8354
|
+
if (!draggedTooltip) return;
|
|
8355
|
+
const tooltipWidth = 200;
|
|
8356
|
+
const tooltipHeight = 80;
|
|
8357
|
+
const globalTooltips = [];
|
|
8358
|
+
window.dispatchEvent(
|
|
8359
|
+
new CustomEvent("requestGlobalTooltips", {
|
|
8360
|
+
detail: { requesterId: draggedTooltipId }
|
|
8361
|
+
})
|
|
8362
|
+
);
|
|
8363
|
+
activeTooltips.forEach((tooltip) => {
|
|
8364
|
+
if (tooltip.id !== draggedTooltipId) {
|
|
8365
|
+
globalTooltips.push({
|
|
8366
|
+
top: tooltip.position.top,
|
|
8367
|
+
left: tooltip.position.left,
|
|
8368
|
+
width: tooltipWidth,
|
|
8369
|
+
height: tooltipHeight,
|
|
8370
|
+
id: tooltip.id
|
|
8371
|
+
});
|
|
8372
|
+
}
|
|
8373
|
+
});
|
|
8374
|
+
const newGuides = [];
|
|
8375
|
+
globalTooltips.forEach((otherTooltip) => {
|
|
8376
|
+
const draggedCenter = {
|
|
8377
|
+
x: draggedPosition.left + tooltipWidth / 2,
|
|
8378
|
+
y: draggedPosition.top + tooltipHeight / 2
|
|
8379
|
+
};
|
|
8380
|
+
const otherCenter = {
|
|
8381
|
+
x: otherTooltip.left + otherTooltip.width / 2,
|
|
8382
|
+
y: otherTooltip.top + otherTooltip.height / 2
|
|
8383
|
+
};
|
|
8384
|
+
const horizontalDistance = Math.abs(draggedCenter.y - otherCenter.y);
|
|
8385
|
+
if (horizontalDistance <= SNAP_THRESHOLD) {
|
|
8386
|
+
newGuides.push({
|
|
8387
|
+
type: "horizontal",
|
|
8388
|
+
position: otherCenter.y,
|
|
8389
|
+
visible: true,
|
|
8390
|
+
sourceTooltip: {
|
|
8391
|
+
top: draggedPosition.top,
|
|
8392
|
+
left: draggedPosition.left,
|
|
8393
|
+
width: tooltipWidth,
|
|
8394
|
+
height: tooltipHeight
|
|
8395
|
+
},
|
|
8396
|
+
targetTooltip: {
|
|
8397
|
+
top: otherTooltip.top,
|
|
8398
|
+
left: otherTooltip.left,
|
|
8399
|
+
width: otherTooltip.width,
|
|
8400
|
+
height: otherTooltip.height
|
|
8401
|
+
}
|
|
8402
|
+
});
|
|
8403
|
+
}
|
|
8404
|
+
const verticalDistance = Math.abs(draggedCenter.x - otherCenter.x);
|
|
8405
|
+
if (verticalDistance <= SNAP_THRESHOLD) {
|
|
8406
|
+
newGuides.push({
|
|
8407
|
+
type: "vertical",
|
|
8408
|
+
position: otherCenter.x,
|
|
8409
|
+
visible: true,
|
|
8410
|
+
sourceTooltip: {
|
|
8411
|
+
top: draggedPosition.top,
|
|
8412
|
+
left: draggedPosition.left,
|
|
8413
|
+
width: tooltipWidth,
|
|
8414
|
+
height: tooltipHeight
|
|
8415
|
+
},
|
|
8416
|
+
targetTooltip: {
|
|
8417
|
+
top: otherTooltip.top,
|
|
8418
|
+
left: otherTooltip.left,
|
|
8419
|
+
width: otherTooltip.width,
|
|
8420
|
+
height: otherTooltip.height
|
|
8421
|
+
}
|
|
8422
|
+
});
|
|
8423
|
+
}
|
|
8424
|
+
});
|
|
8425
|
+
setAlignmentGuides(newGuides);
|
|
8426
|
+
},
|
|
8427
|
+
[activeTooltips]
|
|
8428
|
+
);
|
|
8429
|
+
const snapToGuides = (0, import_react37.useCallback)(
|
|
8430
|
+
(position) => {
|
|
8431
|
+
const SNAP_DISTANCE = 10;
|
|
8432
|
+
const snappedPosition = { ...position };
|
|
8433
|
+
alignmentGuides.forEach((guide) => {
|
|
8434
|
+
if (guide.type === "horizontal") {
|
|
8435
|
+
const tooltipCenter = position.top + 40;
|
|
8436
|
+
if (Math.abs(tooltipCenter - guide.position) <= SNAP_DISTANCE) {
|
|
8437
|
+
snappedPosition.top = guide.position - 40;
|
|
8438
|
+
}
|
|
8439
|
+
} else if (guide.type === "vertical") {
|
|
8440
|
+
const tooltipCenter = position.left + 100;
|
|
8441
|
+
if (Math.abs(tooltipCenter - guide.position) <= SNAP_DISTANCE) {
|
|
8442
|
+
snappedPosition.left = guide.position - 100;
|
|
8443
|
+
}
|
|
8444
|
+
}
|
|
8445
|
+
});
|
|
8446
|
+
return snappedPosition;
|
|
8447
|
+
},
|
|
8448
|
+
[alignmentGuides]
|
|
8449
|
+
);
|
|
8450
|
+
const handleMouseDown = (tooltipId, e) => {
|
|
8451
|
+
const rect = e.target.getBoundingClientRect();
|
|
8452
|
+
const offsetX = e.clientX - rect.left;
|
|
8453
|
+
const offsetY = e.clientY - rect.top;
|
|
8454
|
+
setIsDragging(tooltipId);
|
|
8455
|
+
setDragOffset({ x: offsetX, y: offsetY });
|
|
8456
|
+
};
|
|
8457
|
+
(0, import_react37.useEffect)(() => {
|
|
8458
|
+
let rafId;
|
|
8459
|
+
let lastMousePosition = { x: 0, y: 0 };
|
|
8460
|
+
const handleGlobalMouseMove = (e) => {
|
|
8461
|
+
if (!isDragging) return;
|
|
8462
|
+
lastMousePosition = { x: e.clientX, y: e.clientY };
|
|
8463
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
8464
|
+
rafId = requestAnimationFrame(() => {
|
|
8465
|
+
const newLeft = lastMousePosition.x - dragOffset.x;
|
|
8466
|
+
const newTop = lastMousePosition.y - dragOffset.y;
|
|
8467
|
+
let finalPosition = { top: newTop, left: newLeft };
|
|
8468
|
+
finalPosition = snapToGuides(finalPosition);
|
|
8469
|
+
setActiveTooltips(
|
|
8470
|
+
(prev) => prev.map(
|
|
8471
|
+
(tooltip) => tooltip.id === isDragging ? { ...tooltip, position: finalPosition } : tooltip
|
|
8472
|
+
)
|
|
8473
|
+
);
|
|
8474
|
+
updateAlignmentGuides(isDragging, finalPosition);
|
|
8475
|
+
});
|
|
8476
|
+
};
|
|
8477
|
+
const handleGlobalMouseUp = () => {
|
|
8478
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
8479
|
+
setIsDragging(null);
|
|
8480
|
+
setAlignmentGuides([]);
|
|
8481
|
+
document.body.style.cursor = "";
|
|
8482
|
+
document.body.style.userSelect = "";
|
|
8483
|
+
};
|
|
8484
|
+
if (isDragging) {
|
|
8485
|
+
document.body.style.cursor = "grabbing";
|
|
8486
|
+
document.body.style.userSelect = "none";
|
|
8487
|
+
window.addEventListener("mousemove", handleGlobalMouseMove);
|
|
8488
|
+
window.addEventListener("mouseup", handleGlobalMouseUp);
|
|
8489
|
+
}
|
|
8490
|
+
return () => {
|
|
8491
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
8492
|
+
window.removeEventListener("mousemove", handleGlobalMouseMove);
|
|
8493
|
+
window.removeEventListener("mouseup", handleGlobalMouseUp);
|
|
8494
|
+
document.body.style.cursor = "";
|
|
8495
|
+
document.body.style.userSelect = "";
|
|
8496
|
+
};
|
|
8497
|
+
}, [
|
|
8498
|
+
isDragging,
|
|
8499
|
+
dragOffset,
|
|
8500
|
+
alignmentGuides,
|
|
8501
|
+
updateAlignmentGuides,
|
|
8502
|
+
snapToGuides
|
|
8503
|
+
]);
|
|
8504
|
+
(0, import_react37.useEffect)(() => {
|
|
8505
|
+
const handleCloseAllTooltips2 = () => {
|
|
8506
|
+
setActiveTooltips([]);
|
|
8507
|
+
setGlobalTooltipCount(0);
|
|
8508
|
+
};
|
|
8509
|
+
window.addEventListener("closeAllTooltips", handleCloseAllTooltips2);
|
|
8510
|
+
return () => {
|
|
8511
|
+
window.removeEventListener("closeAllTooltips", handleCloseAllTooltips2);
|
|
8512
|
+
};
|
|
8513
|
+
}, []);
|
|
8514
|
+
(0, import_react37.useEffect)(() => {
|
|
8515
|
+
const handleTooltipCountRequest = () => {
|
|
8516
|
+
window.dispatchEvent(
|
|
8517
|
+
new CustomEvent("tooltipCountResponse", {
|
|
8518
|
+
detail: { count: activeTooltips.length }
|
|
8519
|
+
})
|
|
8520
|
+
);
|
|
8521
|
+
};
|
|
8522
|
+
const handleGlobalTooltipsRequest = (event) => {
|
|
8523
|
+
const requesterId = event.detail?.requesterId;
|
|
8524
|
+
activeTooltips.forEach((tooltip) => {
|
|
8525
|
+
if (tooltip.id !== requesterId) {
|
|
8526
|
+
window.dispatchEvent(
|
|
8527
|
+
new CustomEvent("globalTooltipResponse", {
|
|
8528
|
+
detail: {
|
|
8529
|
+
tooltip: {
|
|
8530
|
+
top: tooltip.position.top,
|
|
8531
|
+
left: tooltip.position.left,
|
|
8532
|
+
width: 200,
|
|
8533
|
+
height: 80,
|
|
8534
|
+
id: tooltip.id
|
|
8535
|
+
}
|
|
8536
|
+
}
|
|
8537
|
+
})
|
|
8538
|
+
);
|
|
8539
|
+
}
|
|
8540
|
+
});
|
|
8541
|
+
};
|
|
8542
|
+
window.addEventListener("requestTooltipCount", handleTooltipCountRequest);
|
|
8543
|
+
window.addEventListener(
|
|
8544
|
+
"requestGlobalTooltips",
|
|
8545
|
+
handleGlobalTooltipsRequest
|
|
8546
|
+
);
|
|
8547
|
+
return () => {
|
|
8548
|
+
window.removeEventListener(
|
|
8549
|
+
"requestTooltipCount",
|
|
8550
|
+
handleTooltipCountRequest
|
|
8551
|
+
);
|
|
8552
|
+
window.removeEventListener(
|
|
8553
|
+
"requestGlobalTooltips",
|
|
8554
|
+
handleGlobalTooltipsRequest
|
|
8555
|
+
);
|
|
8556
|
+
};
|
|
8557
|
+
}, [activeTooltips]);
|
|
8558
|
+
(0, import_react37.useEffect)(() => {
|
|
8559
|
+
if (isDragging) return;
|
|
8560
|
+
let totalCount = 0;
|
|
8561
|
+
const handleCountResponse = (event) => {
|
|
8562
|
+
const customEvent = event;
|
|
8563
|
+
totalCount += customEvent.detail.count;
|
|
8564
|
+
};
|
|
8565
|
+
window.addEventListener("tooltipCountResponse", handleCountResponse);
|
|
8566
|
+
window.dispatchEvent(new CustomEvent("requestTooltipCount"));
|
|
8567
|
+
const timeoutId = setTimeout(() => {
|
|
8568
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
8569
|
+
setGlobalTooltipCount(totalCount);
|
|
8570
|
+
}, 5);
|
|
8571
|
+
return () => {
|
|
8572
|
+
clearTimeout(timeoutId);
|
|
8573
|
+
window.removeEventListener("tooltipCountResponse", handleCountResponse);
|
|
8574
|
+
};
|
|
8575
|
+
}, [activeTooltips.length, isDragging]);
|
|
8576
|
+
const getTitleClass = () => {
|
|
8577
|
+
switch (titlePosition) {
|
|
8578
|
+
case "center":
|
|
8579
|
+
return "text-center";
|
|
8580
|
+
case "right":
|
|
8581
|
+
return "text-right";
|
|
8582
|
+
default:
|
|
8583
|
+
return "text-left";
|
|
8584
|
+
}
|
|
6734
8585
|
};
|
|
8586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: cn("relative", className), children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
|
|
8587
|
+
"div",
|
|
8588
|
+
{
|
|
8589
|
+
className: "rounded-lg bg-card p-4 relative border border-border",
|
|
8590
|
+
style: {
|
|
8591
|
+
width: typeof width === "number" ? `${width + 32}px` : "fit-content",
|
|
8592
|
+
maxWidth: "100%"
|
|
8593
|
+
},
|
|
8594
|
+
onClick: handleChartBackgroundClick,
|
|
8595
|
+
children: [
|
|
8596
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { style: { paddingLeft: `${resolvedContainerPaddingLeft}px` }, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: cn("mb-4", getTitleClass()), children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: title }) }) }),
|
|
8597
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
|
|
8598
|
+
import_recharts3.LineChart,
|
|
8599
|
+
{
|
|
8600
|
+
data,
|
|
8601
|
+
width: typeof width === "number" ? width : 900,
|
|
8602
|
+
height,
|
|
8603
|
+
margin: resolveChartMargins(margins, chartMargins, showLabels),
|
|
8604
|
+
onClick: handleChartClick,
|
|
8605
|
+
children: [
|
|
8606
|
+
showGrid && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8607
|
+
import_recharts3.CartesianGrid,
|
|
8608
|
+
{
|
|
8609
|
+
strokeDasharray: "3 3",
|
|
8610
|
+
stroke: gridColor || "hsl(var(--muted-foreground))",
|
|
8611
|
+
opacity: 0.3
|
|
8612
|
+
}
|
|
8613
|
+
),
|
|
8614
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8615
|
+
import_recharts3.XAxis,
|
|
8616
|
+
{
|
|
8617
|
+
dataKey: "name",
|
|
8618
|
+
className: "fill-muted-foreground text-xs",
|
|
8619
|
+
fontSize: 12
|
|
8620
|
+
}
|
|
8621
|
+
),
|
|
8622
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8623
|
+
import_recharts3.YAxis,
|
|
8624
|
+
{
|
|
8625
|
+
className: "fill-muted-foreground text-xs",
|
|
8626
|
+
fontSize: 12,
|
|
8627
|
+
tickFormatter: (value) => compactTick(Number(value)),
|
|
8628
|
+
domain: [0, niceMax],
|
|
8629
|
+
tickCount: 6
|
|
8630
|
+
}
|
|
8631
|
+
),
|
|
8632
|
+
showTooltip && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_recharts3.Tooltip, { content: () => null }),
|
|
8633
|
+
showLegend && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8634
|
+
import_recharts3.Legend,
|
|
8635
|
+
{
|
|
8636
|
+
wrapperStyle: {
|
|
8637
|
+
fontSize: "12px",
|
|
8638
|
+
color: "hsl(var(--muted-foreground))"
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
),
|
|
8642
|
+
dataKeys.map((key) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8643
|
+
import_recharts3.Line,
|
|
8644
|
+
{
|
|
8645
|
+
type: "monotone",
|
|
8646
|
+
dataKey: key,
|
|
8647
|
+
stroke: finalColors[key],
|
|
8648
|
+
strokeWidth,
|
|
8649
|
+
dot: showDots ? { r: 4, cursor: "pointer" } : false,
|
|
8650
|
+
activeDot: (props) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(ClickableDot, { ...props, dataKey: key }),
|
|
8651
|
+
children: showLabels && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8652
|
+
import_recharts3.LabelList,
|
|
8653
|
+
{
|
|
8654
|
+
dataKey: key,
|
|
8655
|
+
position: "top",
|
|
8656
|
+
content: pillLabelRenderer_default(
|
|
8657
|
+
finalColors[key] || "#000",
|
|
8658
|
+
"filled"
|
|
8659
|
+
),
|
|
8660
|
+
offset: 14
|
|
8661
|
+
}
|
|
8662
|
+
)
|
|
8663
|
+
},
|
|
8664
|
+
key
|
|
8665
|
+
))
|
|
8666
|
+
]
|
|
8667
|
+
}
|
|
8668
|
+
),
|
|
8669
|
+
alignmentGuides.map((guide, index) => {
|
|
8670
|
+
const isHorizontal = guide.type === "horizontal";
|
|
8671
|
+
const color = isHorizontal ? "#3b82f6" : "#ef4444";
|
|
8672
|
+
const startX = isHorizontal ? Math.min(
|
|
8673
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
8674
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
8675
|
+
) : guide.sourceTooltip.left + (isHorizontal ? 0 : guide.sourceTooltip.width / 2);
|
|
8676
|
+
const endX = isHorizontal ? Math.max(
|
|
8677
|
+
guide.sourceTooltip.left + guide.sourceTooltip.width / 2,
|
|
8678
|
+
guide.targetTooltip.left + guide.targetTooltip.width / 2
|
|
8679
|
+
) : guide.targetTooltip.left + (isHorizontal ? 0 : guide.targetTooltip.width / 2);
|
|
8680
|
+
const startY = isHorizontal ? guide.sourceTooltip.top + (isHorizontal ? guide.sourceTooltip.height / 2 : 0) : Math.min(
|
|
8681
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
8682
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
8683
|
+
);
|
|
8684
|
+
const endY = isHorizontal ? guide.targetTooltip.top + (isHorizontal ? guide.targetTooltip.height / 2 : 0) : Math.max(
|
|
8685
|
+
guide.sourceTooltip.top + guide.sourceTooltip.height / 2,
|
|
8686
|
+
guide.targetTooltip.top + guide.targetTooltip.height / 2
|
|
8687
|
+
);
|
|
8688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { children: [
|
|
8689
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8690
|
+
"div",
|
|
8691
|
+
{
|
|
8692
|
+
className: "fixed pointer-events-none z-30",
|
|
8693
|
+
style: {
|
|
8694
|
+
left: startX,
|
|
8695
|
+
top: startY,
|
|
8696
|
+
width: isHorizontal ? endX - startX : "2px",
|
|
8697
|
+
height: isHorizontal ? "2px" : endY - startY,
|
|
8698
|
+
backgroundColor: color,
|
|
8699
|
+
boxShadow: `0 0 8px ${color}60`,
|
|
8700
|
+
opacity: 0.9,
|
|
8701
|
+
borderStyle: "dashed",
|
|
8702
|
+
borderWidth: "1px",
|
|
8703
|
+
borderColor: color,
|
|
8704
|
+
transform: "translateZ(0)"
|
|
8705
|
+
}
|
|
8706
|
+
}
|
|
8707
|
+
),
|
|
8708
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8709
|
+
"div",
|
|
8710
|
+
{
|
|
8711
|
+
className: "fixed pointer-events-none z-31",
|
|
8712
|
+
style: {
|
|
8713
|
+
left: guide.sourceTooltip.left + guide.sourceTooltip.width / 2 - 4,
|
|
8714
|
+
top: guide.sourceTooltip.top + guide.sourceTooltip.height / 2 - 4,
|
|
8715
|
+
width: "8px",
|
|
8716
|
+
height: "8px",
|
|
8717
|
+
backgroundColor: color,
|
|
8718
|
+
borderRadius: "50%",
|
|
8719
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
8720
|
+
opacity: 0.8
|
|
8721
|
+
}
|
|
8722
|
+
}
|
|
8723
|
+
),
|
|
8724
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8725
|
+
"div",
|
|
8726
|
+
{
|
|
8727
|
+
className: "fixed pointer-events-none z-31",
|
|
8728
|
+
style: {
|
|
8729
|
+
left: guide.targetTooltip.left + guide.targetTooltip.width / 2 - 4,
|
|
8730
|
+
top: guide.targetTooltip.top + guide.targetTooltip.height / 2 - 4,
|
|
8731
|
+
width: "8px",
|
|
8732
|
+
height: "8px",
|
|
8733
|
+
backgroundColor: color,
|
|
8734
|
+
borderRadius: "50%",
|
|
8735
|
+
boxShadow: `0 0 4px ${color}80`,
|
|
8736
|
+
opacity: 0.8
|
|
8737
|
+
}
|
|
8738
|
+
}
|
|
8739
|
+
)
|
|
8740
|
+
] }, index);
|
|
8741
|
+
}),
|
|
8742
|
+
activeTooltips.map((tooltip, index) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
8743
|
+
DraggableTooltip_default,
|
|
8744
|
+
{
|
|
8745
|
+
id: tooltip.id,
|
|
8746
|
+
data: tooltip.data,
|
|
8747
|
+
position: tooltip.position,
|
|
8748
|
+
isDragging: isDragging === tooltip.id,
|
|
8749
|
+
title,
|
|
8750
|
+
dataKeys,
|
|
8751
|
+
finalColors,
|
|
8752
|
+
onMouseDown: (id, e) => handleMouseDown(id, e),
|
|
8753
|
+
onClose: (id) => {
|
|
8754
|
+
setActiveTooltips((prev) => prev.filter((t) => t.id !== id));
|
|
8755
|
+
},
|
|
8756
|
+
periodLabel: "Ponto Selecionado",
|
|
8757
|
+
dataLabel: "Dados do Ponto",
|
|
8758
|
+
showCloseAllButton: index === 0,
|
|
8759
|
+
globalTooltipCount,
|
|
8760
|
+
onCloseAll: handleCloseAllTooltips,
|
|
8761
|
+
closeAllButtonPosition: "top-center",
|
|
8762
|
+
closeAllButtonVariant: "floating"
|
|
8763
|
+
},
|
|
8764
|
+
tooltip.id
|
|
8765
|
+
))
|
|
8766
|
+
]
|
|
8767
|
+
}
|
|
8768
|
+
) });
|
|
6735
8769
|
};
|
|
8770
|
+
var LineChart_default = CustomLineChart;
|
|
6736
8771
|
|
|
6737
|
-
// src/components/charts/
|
|
6738
|
-
var
|
|
6739
|
-
var
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
8772
|
+
// src/components/charts/PieChart.tsx
|
|
8773
|
+
var import_recharts4 = require("recharts");
|
|
8774
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
8775
|
+
var defaultData2 = [
|
|
8776
|
+
{ name: "Vendas", value: 4e3 },
|
|
8777
|
+
{ name: "Marketing", value: 3e3 },
|
|
8778
|
+
{ name: "Desenvolvimento", value: 2e3 },
|
|
8779
|
+
{ name: "Suporte", value: 1e3 },
|
|
8780
|
+
{ name: "Outros", value: 800 }
|
|
8781
|
+
];
|
|
8782
|
+
var DEFAULT_COLORS4 = [
|
|
8783
|
+
"#55af7d",
|
|
8784
|
+
// verde do projeto
|
|
8785
|
+
"#8e68ff",
|
|
8786
|
+
// roxo do projeto
|
|
8787
|
+
"#2273e1",
|
|
8788
|
+
// azul do projeto
|
|
8789
|
+
"#f59e0b",
|
|
8790
|
+
// amarelo complementar
|
|
8791
|
+
"#ef4444",
|
|
8792
|
+
// vermelho complementar
|
|
8793
|
+
"#8b5cf6",
|
|
8794
|
+
// roxo claro
|
|
8795
|
+
"#06b6d4",
|
|
8796
|
+
// ciano
|
|
8797
|
+
"#84cc16"
|
|
8798
|
+
// verde lima
|
|
8799
|
+
];
|
|
8800
|
+
var RADIAN = Math.PI / 180;
|
|
8801
|
+
var renderCustomizedLabel = ({
|
|
8802
|
+
cx = 0,
|
|
8803
|
+
cy = 0,
|
|
8804
|
+
midAngle = 0,
|
|
8805
|
+
innerRadius = 0,
|
|
8806
|
+
outerRadius = 0,
|
|
8807
|
+
percent = 0
|
|
8808
|
+
}) => {
|
|
8809
|
+
const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
|
|
8810
|
+
const x = cx + radius * Math.cos(-midAngle * RADIAN);
|
|
8811
|
+
const y = cy + radius * Math.sin(-midAngle * RADIAN);
|
|
8812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8813
|
+
"text",
|
|
8814
|
+
{
|
|
8815
|
+
x,
|
|
8816
|
+
y,
|
|
8817
|
+
fill: "white",
|
|
8818
|
+
textAnchor: x > cx ? "start" : "end",
|
|
8819
|
+
dominantBaseline: "central",
|
|
8820
|
+
fontSize: 12,
|
|
8821
|
+
fontWeight: "600",
|
|
8822
|
+
children: `${(percent * 100).toFixed(0)}%`
|
|
8823
|
+
}
|
|
8824
|
+
);
|
|
6753
8825
|
};
|
|
6754
|
-
var
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
8826
|
+
var CustomPieChart = ({
|
|
8827
|
+
data = defaultData2,
|
|
8828
|
+
className,
|
|
8829
|
+
height = 400,
|
|
8830
|
+
width = "100%",
|
|
8831
|
+
colors: colors2,
|
|
8832
|
+
showTooltip = true,
|
|
8833
|
+
showLegend = true,
|
|
8834
|
+
showLabels = true,
|
|
8835
|
+
innerRadius = 0,
|
|
8836
|
+
outerRadius = 120,
|
|
8837
|
+
centerX = "50%",
|
|
8838
|
+
centerY = "50%"
|
|
8839
|
+
}) => {
|
|
8840
|
+
const finalColors = colors2 || DEFAULT_COLORS4;
|
|
8841
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: cn("w-full rounded-lg bg-card p-4", className), children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_recharts4.ResponsiveContainer, { width, height, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_recharts4.PieChart, { children: [
|
|
8842
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8843
|
+
import_recharts4.Pie,
|
|
8844
|
+
{
|
|
8845
|
+
data,
|
|
8846
|
+
cx: centerX,
|
|
8847
|
+
cy: centerY,
|
|
8848
|
+
labelLine: false,
|
|
8849
|
+
label: showLabels ? renderCustomizedLabel : false,
|
|
8850
|
+
outerRadius,
|
|
8851
|
+
innerRadius,
|
|
8852
|
+
fill: "#8884d8",
|
|
8853
|
+
dataKey: "value",
|
|
8854
|
+
children: data.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8855
|
+
import_recharts4.Cell,
|
|
8856
|
+
{
|
|
8857
|
+
fill: finalColors[index % finalColors.length]
|
|
8858
|
+
},
|
|
8859
|
+
`cell-${entry.name}-${index}`
|
|
8860
|
+
))
|
|
8861
|
+
}
|
|
8862
|
+
),
|
|
8863
|
+
showTooltip && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
8864
|
+
import_recharts4.Tooltip,
|
|
8865
|
+
{
|
|
8866
|
+
contentStyle: {
|
|
8867
|
+
backgroundColor: "hsl(var(--popover))",
|
|
8868
|
+
border: "1px solid hsl(var(--border))",
|
|
8869
|
+
borderRadius: "6px",
|
|
8870
|
+
color: "hsl(var(--popover-foreground))"
|
|
8871
|
+
}
|
|
8872
|
+
}
|
|
8873
|
+
),
|
|
8874
|
+
showLegend && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_recharts4.Legend, {})
|
|
8875
|
+
] }) }) });
|
|
6759
8876
|
};
|
|
6760
|
-
var
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
const vb = props.viewBox;
|
|
6775
|
-
const cxNum = parseNumber(props.cx);
|
|
6776
|
-
let centerX;
|
|
6777
|
-
if (typeof px === "number" && typeof pWidth === "number") {
|
|
6778
|
-
centerX = px + pWidth / 2;
|
|
6779
|
-
} else if (typeof xNum === "number" && typeof pWidth === "number") {
|
|
6780
|
-
centerX = xNum + pWidth / 2;
|
|
6781
|
-
} else if (typeof cxNum === "number") {
|
|
6782
|
-
centerX = cxNum;
|
|
6783
|
-
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number" && typeof props.index === "number") {
|
|
6784
|
-
const approxCols = Math.max(1, props.index + 1);
|
|
6785
|
-
const colWidth = vb.width / approxCols;
|
|
6786
|
-
centerX = vb.x + colWidth * (props.index + 0.5);
|
|
6787
|
-
} else if (vb && typeof vb.x === "number" && typeof vb.width === "number") {
|
|
6788
|
-
centerX = vb.x + vb.width / 2;
|
|
6789
|
-
} else {
|
|
6790
|
-
centerX = typeof props.index === "number" ? props.index * 40 + 24 : 0;
|
|
6791
|
-
}
|
|
6792
|
-
if (vb && typeof vb.x === "number" && typeof vb.width === "number") {
|
|
6793
|
-
const minX = vb.x + 0 + pillWidth / 22;
|
|
6794
|
-
const maxX = vb.x + vb.width - 2 - pillWidth / 2;
|
|
6795
|
-
centerX = Math.max(minX, Math.min(maxX, centerX));
|
|
6796
|
-
}
|
|
6797
|
-
const yNum = parseNumber(y);
|
|
6798
|
-
const py = parseNumber(props.y);
|
|
6799
|
-
const cyNum = parseNumber(props.cy);
|
|
6800
|
-
const centerY = yNum ?? (typeof py === "number" ? py : vb && typeof vb.y === "number" && typeof vb.height === "number" ? vb.y + vb.height / 2 : typeof cyNum === "number" ? cyNum : 0);
|
|
6801
|
-
const rectX = centerX - pillWidth / 2;
|
|
6802
|
-
const rectY = centerY - pillHeight - 6;
|
|
6803
|
-
const textX = centerX;
|
|
6804
|
-
const textY = rectY + pillHeight / 2 + 3;
|
|
6805
|
-
const rectFill = variant === "filled" ? color : variant === "soft" ? `${color}20` : "#ffffff";
|
|
6806
|
-
const rectStroke = variant === "outline" ? `${color}CC` : void 0;
|
|
6807
|
-
const numValue = parseNumber(value);
|
|
6808
|
-
const isNegative = typeof numValue === "number" && numValue < 0;
|
|
6809
|
-
let textColor;
|
|
6810
|
-
if (isNegative) {
|
|
6811
|
-
textColor = "#dc2626";
|
|
6812
|
-
} else {
|
|
6813
|
-
if (variant === "filled") {
|
|
6814
|
-
textColor = "#ffffff";
|
|
8877
|
+
var PieChart_default = CustomPieChart;
|
|
8878
|
+
|
|
8879
|
+
// src/components/charts/hooks/useChartHighlights.tsx
|
|
8880
|
+
var import_react38 = require("react");
|
|
8881
|
+
var useChartHighlights = () => {
|
|
8882
|
+
const [highlightedSeries, setHighlightedSeries] = (0, import_react38.useState)(
|
|
8883
|
+
/* @__PURE__ */ new Set()
|
|
8884
|
+
);
|
|
8885
|
+
const [showOnlyHighlighted, setShowOnlyHighlighted] = (0, import_react38.useState)(false);
|
|
8886
|
+
const toggleHighlight = (0, import_react38.useCallback)((key) => {
|
|
8887
|
+
setHighlightedSeries((prev) => {
|
|
8888
|
+
const next = new Set(prev);
|
|
8889
|
+
if (next.has(key)) {
|
|
8890
|
+
next.delete(key);
|
|
6815
8891
|
} else {
|
|
6816
|
-
|
|
8892
|
+
next.add(key);
|
|
6817
8893
|
}
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
8894
|
+
return next;
|
|
8895
|
+
});
|
|
8896
|
+
}, []);
|
|
8897
|
+
const clearHighlights = (0, import_react38.useCallback)(() => {
|
|
8898
|
+
setHighlightedSeries(/* @__PURE__ */ new Set());
|
|
8899
|
+
setShowOnlyHighlighted(false);
|
|
8900
|
+
}, []);
|
|
8901
|
+
const isHighlighted = (0, import_react38.useCallback)(
|
|
8902
|
+
(key) => {
|
|
8903
|
+
return highlightedSeries.has(key);
|
|
8904
|
+
},
|
|
8905
|
+
[highlightedSeries]
|
|
8906
|
+
);
|
|
8907
|
+
const getSeriesStyle = (0, import_react38.useCallback)(
|
|
8908
|
+
(key) => {
|
|
8909
|
+
const hasHighlights = highlightedSeries.size > 0;
|
|
8910
|
+
const isSeriesHighlighted = highlightedSeries.has(key);
|
|
8911
|
+
if (showOnlyHighlighted && !isSeriesHighlighted) {
|
|
8912
|
+
return {
|
|
8913
|
+
opacity: 0,
|
|
8914
|
+
pointerEvents: "none",
|
|
8915
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8916
|
+
};
|
|
8917
|
+
}
|
|
8918
|
+
if (!hasHighlights) {
|
|
8919
|
+
return {
|
|
8920
|
+
opacity: 1,
|
|
8921
|
+
transform: "scale(1)",
|
|
8922
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8923
|
+
};
|
|
8924
|
+
}
|
|
8925
|
+
if (isSeriesHighlighted) {
|
|
8926
|
+
return {
|
|
8927
|
+
opacity: 1,
|
|
8928
|
+
transform: "scale(1.02)",
|
|
8929
|
+
filter: "drop-shadow(0 4px 12px rgba(0, 0, 0, 0.15))",
|
|
8930
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8931
|
+
};
|
|
8932
|
+
}
|
|
8933
|
+
return {
|
|
8934
|
+
opacity: 0.25,
|
|
8935
|
+
transform: "scale(0.98)",
|
|
8936
|
+
transition: "all 300ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
8937
|
+
};
|
|
8938
|
+
},
|
|
8939
|
+
[highlightedSeries, showOnlyHighlighted]
|
|
8940
|
+
);
|
|
8941
|
+
return {
|
|
8942
|
+
highlightedSeries,
|
|
8943
|
+
showOnlyHighlighted,
|
|
8944
|
+
toggleHighlight,
|
|
8945
|
+
setShowOnlyHighlighted,
|
|
8946
|
+
clearHighlights,
|
|
8947
|
+
getSeriesStyle,
|
|
8948
|
+
isHighlighted
|
|
6848
8949
|
};
|
|
6849
8950
|
};
|
|
6850
|
-
var pillLabelRenderer_default = renderPillLabel;
|
|
6851
8951
|
|
|
6852
8952
|
// src/hooks/use-drag.tsx
|
|
6853
|
-
var
|
|
8953
|
+
var import_react39 = require("react");
|
|
6854
8954
|
var useDrag = (options = {}) => {
|
|
6855
|
-
const [isDragging, setIsDragging] = (0,
|
|
6856
|
-
const [positions, setPositions] = (0,
|
|
6857
|
-
const dragStartPos = (0,
|
|
6858
|
-
const dragId = (0,
|
|
6859
|
-
const handleMouseDown = (0,
|
|
8955
|
+
const [isDragging, setIsDragging] = (0, import_react39.useState)(null);
|
|
8956
|
+
const [positions, setPositions] = (0, import_react39.useState)({});
|
|
8957
|
+
const dragStartPos = (0, import_react39.useRef)(null);
|
|
8958
|
+
const dragId = (0, import_react39.useRef)(null);
|
|
8959
|
+
const handleMouseDown = (0, import_react39.useCallback)((id, e) => {
|
|
6860
8960
|
e.preventDefault();
|
|
6861
8961
|
const currentPosition = positions[id] || { top: 0, left: 0 };
|
|
6862
8962
|
dragStartPos.current = {
|
|
@@ -6869,7 +8969,7 @@ var useDrag = (options = {}) => {
|
|
|
6869
8969
|
setIsDragging(id);
|
|
6870
8970
|
options.onDragStart?.(id);
|
|
6871
8971
|
}, [positions, options]);
|
|
6872
|
-
const handleMouseMove = (0,
|
|
8972
|
+
const handleMouseMove = (0, import_react39.useCallback)((e) => {
|
|
6873
8973
|
if (!isDragging || !dragStartPos.current || !dragId.current) return;
|
|
6874
8974
|
const deltaX = e.clientX - dragStartPos.current.x;
|
|
6875
8975
|
const deltaY = e.clientY - dragStartPos.current.y;
|
|
@@ -6885,7 +8985,7 @@ var useDrag = (options = {}) => {
|
|
|
6885
8985
|
}));
|
|
6886
8986
|
options.onDrag?.(dragId.current, newPosition);
|
|
6887
8987
|
}, [isDragging, options]);
|
|
6888
|
-
const handleMouseUp = (0,
|
|
8988
|
+
const handleMouseUp = (0, import_react39.useCallback)(() => {
|
|
6889
8989
|
if (dragId.current) {
|
|
6890
8990
|
options.onDragEnd?.(dragId.current);
|
|
6891
8991
|
}
|
|
@@ -6893,7 +8993,7 @@ var useDrag = (options = {}) => {
|
|
|
6893
8993
|
dragStartPos.current = null;
|
|
6894
8994
|
dragId.current = null;
|
|
6895
8995
|
}, [options]);
|
|
6896
|
-
(0,
|
|
8996
|
+
(0, import_react39.useEffect)(() => {
|
|
6897
8997
|
if (isDragging) {
|
|
6898
8998
|
document.addEventListener("mousemove", handleMouseMove);
|
|
6899
8999
|
document.addEventListener("mouseup", handleMouseUp);
|
|
@@ -6905,16 +9005,16 @@ var useDrag = (options = {}) => {
|
|
|
6905
9005
|
};
|
|
6906
9006
|
}
|
|
6907
9007
|
}, [isDragging, handleMouseMove, handleMouseUp]);
|
|
6908
|
-
const setPosition = (0,
|
|
9008
|
+
const setPosition = (0, import_react39.useCallback)((id, position) => {
|
|
6909
9009
|
setPositions((prev) => ({
|
|
6910
9010
|
...prev,
|
|
6911
9011
|
[id]: position
|
|
6912
9012
|
}));
|
|
6913
9013
|
}, []);
|
|
6914
|
-
const getPosition = (0,
|
|
9014
|
+
const getPosition = (0, import_react39.useCallback)((id) => {
|
|
6915
9015
|
return positions[id] || { top: 0, left: 0 };
|
|
6916
9016
|
}, [positions]);
|
|
6917
|
-
const isElementDragging = (0,
|
|
9017
|
+
const isElementDragging = (0, import_react39.useCallback)((id) => {
|
|
6918
9018
|
return isDragging === id;
|
|
6919
9019
|
}, [isDragging]);
|
|
6920
9020
|
return {
|