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