@mlw-packages/react-components 1.7.3 → 1.7.4

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
@@ -2456,7 +2456,8 @@ var DraggableTooltipComponent = ({
2456
2456
  highlightedSeries,
2457
2457
  toggleHighlight,
2458
2458
  showOnlyHighlighted,
2459
- valueFormatter: valueFormatter2
2459
+ valueFormatter: valueFormatter2,
2460
+ categoryFormatter
2460
2461
  }) => {
2461
2462
  const visibleKeys = useMemo4(
2462
2463
  () => showOnlyHighlighted && highlightedSeries && highlightedSeries.size > 0 ? dataKeys.filter((k) => highlightedSeries.has(k)) : dataKeys,
@@ -2864,7 +2865,7 @@ var DraggableTooltipComponent = ({
2864
2865
  /* @__PURE__ */ jsx23("div", { className: "px-3 py-2 bg-accent/5 border-l-4 border-primary", children: /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between gap-2", children: [
2865
2866
  /* @__PURE__ */ jsxs17("div", { children: [
2866
2867
  /* @__PURE__ */ jsx23("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: periodLabel }),
2867
- /* @__PURE__ */ jsx23("p", { className: "font-bold text-lg text-foreground mt-1 truncate", children: data.name })
2868
+ /* @__PURE__ */ jsx23("p", { className: "font-bold text-lg text-foreground mt-1 truncate", children: categoryFormatter ? categoryFormatter(String(data.name)) : data.name })
2868
2869
  ] }),
2869
2870
  /* @__PURE__ */ jsx23("div", { className: "text-right", children: /* @__PURE__ */ jsx23(
2870
2871
  TotalDisplay,
@@ -3008,15 +3009,28 @@ var RechartTooltipWithTotal = ({
3008
3009
  finalColors = {},
3009
3010
  periodLabel = "Per\xEDodo",
3010
3011
  totalLabel = "Total",
3011
- valueFormatter: valueFormatter2
3012
+ valueFormatter: valueFormatter2,
3013
+ categoryFormatter
3012
3014
  }) => {
3013
3015
  if (!active || !payload || payload.length === 0) return null;
3016
+ const displayLabel = categoryFormatter ? categoryFormatter(String(label ?? "")) : label;
3014
3017
  const numeric = payload.filter(
3015
3018
  (p) => typeof p.value === "number" && Number.isFinite(p.value)
3016
3019
  );
3017
3020
  const total = numeric.reduce((sum, p) => sum + (p.value || 0), 0);
3018
3021
  const isTotalNegative = total < 0;
3019
- const defaultTotalFormatted = total.toLocaleString("pt-BR");
3022
+ const defaultTotalFormatted = (() => {
3023
+ try {
3024
+ if (Math.abs(total) < 1e3) {
3025
+ return new Intl.NumberFormat("pt-BR", {
3026
+ minimumFractionDigits: 2,
3027
+ maximumFractionDigits: 2
3028
+ }).format(total);
3029
+ }
3030
+ } catch {
3031
+ }
3032
+ return total.toLocaleString("pt-BR");
3033
+ })();
3020
3034
  const displayTotal = valueFormatter2 ? valueFormatter2({
3021
3035
  value: total,
3022
3036
  formattedValue: defaultTotalFormatted,
@@ -3038,7 +3052,7 @@ var RechartTooltipWithTotal = ({
3038
3052
  /* @__PURE__ */ jsxs18("div", { className: "flex items-start justify-between mb-2", children: [
3039
3053
  /* @__PURE__ */ jsxs18("div", { className: "pr-2", children: [
3040
3054
  /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: periodLabel }),
3041
- /* @__PURE__ */ jsx24("p", { className: "font-medium text-foreground truncate", children: label })
3055
+ /* @__PURE__ */ jsx24("p", { className: "font-medium text-foreground truncate", children: displayLabel })
3042
3056
  ] }),
3043
3057
  /* @__PURE__ */ jsxs18("div", { className: "text-right ml-3", children: [
3044
3058
  /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: totalLabel }),
@@ -3056,7 +3070,18 @@ var RechartTooltipWithTotal = ({
3056
3070
  const pct = absDenominator > 0 ? Math.abs(value) / absDenominator * 100 : 0;
3057
3071
  const baseColor = finalColors[entry.dataKey] || entry.color || "#999";
3058
3072
  const isNeg = value < 0;
3059
- const defaultFormatted = value.toLocaleString("pt-BR");
3073
+ const defaultFormatted = (() => {
3074
+ try {
3075
+ if (Math.abs(value) < 1e3) {
3076
+ return new Intl.NumberFormat("pt-BR", {
3077
+ minimumFractionDigits: 2,
3078
+ maximumFractionDigits: 2
3079
+ }).format(value);
3080
+ }
3081
+ } catch {
3082
+ }
3083
+ return value.toLocaleString("pt-BR");
3084
+ })();
3060
3085
  const displayValue = valueFormatter2 ? valueFormatter2({
3061
3086
  value: entry.value,
3062
3087
  formattedValue: defaultFormatted,
@@ -3113,9 +3138,11 @@ var TooltipSimple = ({
3113
3138
  label,
3114
3139
  finalColors = {},
3115
3140
  periodLabel = "Per\xEDodo",
3116
- valueFormatter: valueFormatter2
3141
+ valueFormatter: valueFormatter2,
3142
+ categoryFormatter
3117
3143
  }) => {
3118
3144
  if (!active || !payload || payload.length === 0) return null;
3145
+ const displayLabel = categoryFormatter ? categoryFormatter(String(label ?? "")) : label;
3119
3146
  return /* @__PURE__ */ jsxs19(
3120
3147
  "div",
3121
3148
  {
@@ -3126,12 +3153,23 @@ var TooltipSimple = ({
3126
3153
  children: [
3127
3154
  /* @__PURE__ */ jsx25("div", { className: "mb-2", children: /* @__PURE__ */ jsx25("div", { className: "flex items-center justify-between gap-3", children: /* @__PURE__ */ jsxs19("div", { className: "min-w-0", children: [
3128
3155
  /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: periodLabel }),
3129
- /* @__PURE__ */ jsx25("p", { className: "font-medium text-foreground truncate", children: label })
3156
+ /* @__PURE__ */ jsx25("p", { className: "font-medium text-foreground truncate", children: displayLabel })
3130
3157
  ] }) }) }),
3131
3158
  /* @__PURE__ */ jsx25("div", { className: "divide-y divide-border rounded-md overflow-hidden", children: payload.map((entry, index) => {
3132
3159
  const value = typeof entry.value === "number" ? entry.value : 0;
3133
3160
  const color = finalColors[entry.dataKey] || entry.color || "#999";
3134
- const defaultFormatted = value.toLocaleString("pt-BR");
3161
+ const defaultFormatted = (() => {
3162
+ try {
3163
+ if (Math.abs(value) < 1e3) {
3164
+ return new Intl.NumberFormat("pt-BR", {
3165
+ minimumFractionDigits: 2,
3166
+ maximumFractionDigits: 2
3167
+ }).format(value);
3168
+ }
3169
+ } catch {
3170
+ }
3171
+ return value.toLocaleString("pt-BR");
3172
+ })();
3135
3173
  const displayValue = valueFormatter2 ? valueFormatter2({
3136
3174
  value: entry.value,
3137
3175
  formattedValue: defaultFormatted,
@@ -3183,9 +3221,17 @@ var formatCompactNumber = (value) => {
3183
3221
  } else if (absValue >= 1e6) {
3184
3222
  formatted = (absValue / 1e6).toFixed(1).replace(/\.0$/, "") + "M";
3185
3223
  } else if (absValue >= 1e3) {
3186
- formatted = (absValue / 1e3).toFixed(1).replace(/\.0$/, "") + "K";
3224
+ formatted = (absValue / 1e3).toFixed(1).replace(/\.0$/, "") + " mil";
3187
3225
  } else {
3188
- formatted = absValue.toString();
3226
+ try {
3227
+ const nf = new Intl.NumberFormat("pt-BR", {
3228
+ minimumFractionDigits: 2,
3229
+ maximumFractionDigits: 2
3230
+ });
3231
+ formatted = nf.format(absValue);
3232
+ } catch {
3233
+ formatted = String(absValue).replace(".", ",");
3234
+ }
3189
3235
  }
3190
3236
  return isNegative ? `-${formatted}` : formatted;
3191
3237
  };
@@ -3241,9 +3287,9 @@ var renderPillLabel = (color, variant, valueFormatter2) => {
3241
3287
  const py = parseNumber(props.y);
3242
3288
  const cyNum = parseNumber(props.cy);
3243
3289
  const centerY = yNum ?? (typeof py === "number" ? py : vb && typeof vb.y === "number" && typeof vb.height === "number" ? vb.y + vb.height / 2 : typeof cyNum === "number" ? cyNum : 0);
3244
- const rectX = centerX - pillWidth / 2;
3290
+ const rectX = centerX - pillWidth / 3.5;
3245
3291
  const rectY = centerY - pillHeight - 6;
3246
- const textX = centerX;
3292
+ const textX = centerX - pillWidth / 3.5 + pillWidth / 2;
3247
3293
  const textY = rectY + pillHeight / 2 + 3;
3248
3294
  const rectFill = variant === "filled" ? color : variant === "soft" ? `${color}20` : "#ffffff";
3249
3295
  const rectStroke = variant === "outline" ? `${color}CC` : void 0;
@@ -3264,7 +3310,7 @@ var renderPillLabel = (color, variant, valueFormatter2) => {
3264
3310
  "rect",
3265
3311
  {
3266
3312
  x: rectX,
3267
- y: rectY,
3313
+ y: rectY + 4,
3268
3314
  rx: pillHeight / 2,
3269
3315
  width: pillWidth,
3270
3316
  height: pillHeight,
@@ -3277,7 +3323,7 @@ var renderPillLabel = (color, variant, valueFormatter2) => {
3277
3323
  "text",
3278
3324
  {
3279
3325
  x: textX,
3280
- y: textY - 3,
3326
+ y: textY + 2,
3281
3327
  fill: textColor,
3282
3328
  fontSize: 13,
3283
3329
  fontWeight: 700,
@@ -3310,14 +3356,18 @@ var Chart = ({
3310
3356
  titlePosition = "left",
3311
3357
  showLabels = false,
3312
3358
  xAxis,
3359
+ xAxisLabel,
3360
+ yAxisLabel,
3313
3361
  labelMap,
3314
3362
  valueFormatter: valueFormatter2,
3363
+ categoryFormatter,
3315
3364
  enableHighlights = false,
3316
3365
  enableShowOnly = false,
3317
3366
  enablePeriodsDropdown = false,
3318
3367
  enableDraggableTooltips = false,
3319
3368
  showTooltipTotal = false,
3320
3369
  maxTooltips = 5,
3370
+ formatBR = false,
3321
3371
  chartMargin
3322
3372
  }) => {
3323
3373
  const smartConfig = useMemo5(() => {
@@ -3570,6 +3620,68 @@ var Chart = ({
3570
3620
  () => "text-xl font-semibold text-foreground mb-3",
3571
3621
  []
3572
3622
  );
3623
+ const finalValueFormatter = useMemo5(() => {
3624
+ const nf = new Intl.NumberFormat("pt-BR", {
3625
+ minimumFractionDigits: 2,
3626
+ maximumFractionDigits: 2
3627
+ });
3628
+ if (valueFormatter2) {
3629
+ if (formatBR) {
3630
+ const wrapped = (props) => {
3631
+ const { value, formattedValue } = props;
3632
+ let num = NaN;
3633
+ if (typeof value === "number") num = value;
3634
+ else if (typeof value === "string" && value.trim() !== "") {
3635
+ const parsed = Number(value);
3636
+ num = Number.isNaN(parsed) ? NaN : parsed;
3637
+ }
3638
+ const brFormatted = !Number.isNaN(num) ? nf.format(num) : String(formattedValue ?? value ?? "");
3639
+ return valueFormatter2({
3640
+ ...props,
3641
+ formattedValue: brFormatted,
3642
+ value: void 0
3643
+ });
3644
+ };
3645
+ return wrapped;
3646
+ }
3647
+ return valueFormatter2;
3648
+ }
3649
+ if (!formatBR) return void 0;
3650
+ const builtIn = (props) => {
3651
+ const { value, formattedValue } = props;
3652
+ let num = NaN;
3653
+ if (typeof value === "number") num = value;
3654
+ else if (typeof value === "string" && value.trim() !== "") {
3655
+ const parsed = Number(value);
3656
+ num = Number.isNaN(parsed) ? NaN : parsed;
3657
+ }
3658
+ if (!Number.isNaN(num)) return nf.format(num);
3659
+ return String(formattedValue ?? value ?? "");
3660
+ };
3661
+ return builtIn;
3662
+ }, [valueFormatter2, formatBR]);
3663
+ const yTickFormatter = useMemo5(() => {
3664
+ const nf = new Intl.NumberFormat("pt-BR", {
3665
+ minimumFractionDigits: 2,
3666
+ maximumFractionDigits: 2
3667
+ });
3668
+ const stripCurrency = (s) => String(s).replace(/^\s*R\$\s?/, "");
3669
+ if (finalValueFormatter) {
3670
+ return (v) => {
3671
+ const num = Number(String(v));
3672
+ const formatted = Number.isNaN(num) ? String(v ?? "") : nf.format(num);
3673
+ const out = finalValueFormatter({
3674
+ value: v,
3675
+ formattedValue: formatted
3676
+ });
3677
+ return stripCurrency(String(out));
3678
+ };
3679
+ }
3680
+ return (value) => {
3681
+ const num = Number(String(value));
3682
+ return Number.isNaN(num) ? String(value ?? "") : nf.format(num);
3683
+ };
3684
+ }, [finalValueFormatter]);
3573
3685
  const finalEnableHighlights = enableHighlights;
3574
3686
  const finalEnableShowOnly = enableShowOnly;
3575
3687
  const finalEnablePeriodsDropdown = enablePeriodsDropdown && enableDraggableTooltips;
@@ -3577,9 +3689,12 @@ var Chart = ({
3577
3689
  const defaultChartLeftMargin = 0;
3578
3690
  const containerPaddingLeft = 16;
3579
3691
  const finalChartRightMargin = chartMargin?.right ?? defaultChartRightMargin;
3580
- const finalChartLeftMargin = chartMargin?.left ?? defaultChartLeftMargin;
3692
+ const finalChartLeftMargin = chartMargin?.left ?? (yAxisLabel ? 40 : defaultChartLeftMargin);
3581
3693
  const finalChartTopMargin = chartMargin?.top ?? (showLabels ? 48 : 20);
3582
- const finalChartBottomMargin = chartMargin?.bottom ?? 5;
3694
+ const baseBottom = chartMargin?.bottom ?? 5;
3695
+ const extraForXAxisLabel = xAxisLabel ? 22 : 0;
3696
+ const extraForLegend = showLegend ? 36 : 0;
3697
+ const finalChartBottomMargin = baseBottom + extraForXAxisLabel + extraForLegend;
3583
3698
  const measuredInner = measuredWidth ? Math.max(0, measuredWidth - 32) : void 0;
3584
3699
  const effectiveChartWidth = typeof width === "number" ? width : measuredInner ?? computedWidth;
3585
3700
  const chartInnerWidth = effectiveChartWidth - finalChartLeftMargin - finalChartRightMargin;
@@ -3781,7 +3896,23 @@ var Chart = ({
3781
3896
  fontSize: 12,
3782
3897
  tickLine: false,
3783
3898
  axisLine: false,
3784
- tickFormatter: xAxisConfig.valueFormatter
3899
+ tickFormatter: (value) => {
3900
+ if (categoryFormatter)
3901
+ return categoryFormatter(value);
3902
+ if (xAxisConfig.valueFormatter)
3903
+ return xAxisConfig.valueFormatter(value);
3904
+ return String(value ?? "");
3905
+ },
3906
+ label: xAxisLabel ? {
3907
+ value: xAxisLabel,
3908
+ position: "insideBottomRight",
3909
+ offset: -5,
3910
+ style: {
3911
+ fontSize: 12,
3912
+ fill: "hsl(var(--muted-foreground))",
3913
+ fontWeight: 500
3914
+ }
3915
+ } : void 0
3785
3916
  }
3786
3917
  ),
3787
3918
  /* @__PURE__ */ jsx27(
@@ -3791,9 +3922,22 @@ var Chart = ({
3791
3922
  fontSize: 12,
3792
3923
  tickLine: false,
3793
3924
  axisLine: false,
3794
- tickFormatter: (value) => Number(value).toLocaleString("pt-BR"),
3925
+ tickFormatter: yTickFormatter,
3795
3926
  domain: [Math.min(minDataValue, 0), niceMax],
3796
- tickCount: 6
3927
+ tickCount: 6,
3928
+ label: yAxisLabel ? {
3929
+ value: yAxisLabel,
3930
+ angle: -90,
3931
+ // Render the label to the left (outside) of the chart area
3932
+ // to avoid overlapping the Y values / bars.
3933
+ position: "left",
3934
+ style: {
3935
+ fontSize: 12,
3936
+ fill: "hsl(var(--muted-foreground))",
3937
+ fontWeight: 500,
3938
+ textAnchor: "middle"
3939
+ }
3940
+ } : void 0
3797
3941
  }
3798
3942
  ),
3799
3943
  minDataValue < 0 && /* @__PURE__ */ jsx27(
@@ -3812,13 +3956,15 @@ var Chart = ({
3812
3956
  TooltipWithTotal_default,
3813
3957
  {
3814
3958
  finalColors,
3815
- valueFormatter: valueFormatter2
3959
+ valueFormatter: finalValueFormatter,
3960
+ categoryFormatter
3816
3961
  }
3817
3962
  ) : /* @__PURE__ */ jsx27(
3818
3963
  TooltipSimple_default,
3819
3964
  {
3820
3965
  finalColors,
3821
- valueFormatter: valueFormatter2
3966
+ valueFormatter: finalValueFormatter,
3967
+ categoryFormatter
3822
3968
  }
3823
3969
  ),
3824
3970
  cursor: { fill: "hsl(var(--muted))", opacity: 0.1 }
@@ -3829,7 +3975,8 @@ var Chart = ({
3829
3975
  {
3830
3976
  wrapperStyle: {
3831
3977
  color: "hsl(var(--foreground))",
3832
- fontSize: "14px"
3978
+ fontSize: "14px",
3979
+ paddingTop: "8px"
3833
3980
  }
3834
3981
  }
3835
3982
  ),
@@ -3869,7 +4016,7 @@ var Chart = ({
3869
4016
  content: pillLabelRenderer_default(
3870
4017
  color,
3871
4018
  "filled",
3872
- valueFormatter2
4019
+ finalValueFormatter
3873
4020
  ),
3874
4021
  offset: 8
3875
4022
  }
@@ -3902,7 +4049,7 @@ var Chart = ({
3902
4049
  content: pillLabelRenderer_default(
3903
4050
  color,
3904
4051
  "filled",
3905
- valueFormatter2
4052
+ finalValueFormatter
3906
4053
  ),
3907
4054
  offset: 14
3908
4055
  }
@@ -3935,7 +4082,7 @@ var Chart = ({
3935
4082
  content: pillLabelRenderer_default(
3936
4083
  color,
3937
4084
  "soft",
3938
- valueFormatter2
4085
+ finalValueFormatter
3939
4086
  ),
3940
4087
  offset: 12
3941
4088
  }
@@ -3965,7 +4112,8 @@ var Chart = ({
3965
4112
  onPositionChange: onTooltipPositionChange,
3966
4113
  periodLabel: "Per\xEDodo Selecionado",
3967
4114
  dataLabel: "Dados do Per\xEDodo",
3968
- valueFormatter: valueFormatter2,
4115
+ valueFormatter: finalValueFormatter,
4116
+ categoryFormatter,
3969
4117
  globalTooltipCount: activeTooltips.length,
3970
4118
  onCloseAll: () => window.dispatchEvent(new Event("closeAllTooltips")),
3971
4119
  closeAllButtonPosition: "top-center",
@@ -5799,12 +5947,12 @@ var CardFooterBase = React17.forwardRef(({ className, testid: dataTestId = "card
5799
5947
  CardFooterBase.displayName = "CardFooter";
5800
5948
 
5801
5949
  // src/components/ui/data/FileUploader.tsx
5802
- import * as React21 from "react";
5950
+ import * as React18 from "react";
5803
5951
  import { motion as motion10, AnimatePresence as AnimatePresence8 } from "framer-motion";
5804
5952
  import {
5805
5953
  CloudArrowUpIcon,
5806
- CheckIcon as CheckIcon7,
5807
- XIcon as XIcon6,
5954
+ CheckIcon as CheckIcon6,
5955
+ XIcon as XIcon5,
5808
5956
  FileTextIcon,
5809
5957
  FilePdfIcon,
5810
5958
  FileImageIcon,
@@ -5817,2315 +5965,2244 @@ import {
5817
5965
  FilePptIcon,
5818
5966
  FileDocIcon
5819
5967
  } from "@phosphor-icons/react";
5820
-
5821
- // src/components/ui/form/SmallButtons.tsx
5822
- import * as React20 from "react";
5823
-
5824
- // src/components/ui/feedback/DestructiveDialog.tsx
5825
- import * as React19 from "react";
5826
- import { XCircleIcon } from "@phosphor-icons/react";
5827
-
5828
- // src/components/ui/feedback/AlertDialogBase.tsx
5829
- import * as React18 from "react";
5830
- import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
5831
- import { jsx as jsx35, jsxs as jsxs25 } from "react/jsx-runtime";
5832
- var AlertDialogBase = AlertDialogPrimitive.Root;
5833
- var AlertDialogTriggerBase = AlertDialogPrimitive.Trigger;
5834
- var AlertDialogPortalBase = AlertDialogPrimitive.Portal;
5835
- var AlertDialogOverlayBase = React18.forwardRef(({ className, testid = "alertdialog-overlay", ...props }, ref) => /* @__PURE__ */ jsx35(
5836
- AlertDialogPrimitive.Overlay,
5837
- {
5838
- className: cn(
5839
- "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
5840
- className
5841
- ),
5842
- "data-testid": testid,
5843
- ...props,
5844
- ref
5968
+ import { Fragment as Fragment6, jsx as jsx35, jsxs as jsxs25 } from "react/jsx-runtime";
5969
+ var formatFileSize = (bytes) => {
5970
+ if (bytes === 0) return "0 Bytes";
5971
+ const k = 1024;
5972
+ const sizes = ["Bytes", "KB", "MB", "GB"];
5973
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
5974
+ return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
5975
+ };
5976
+ var getFileExtension = (filename) => {
5977
+ return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
5978
+ };
5979
+ var getFileTypeIcon = (file) => {
5980
+ const extension = getFileExtension(file.name).toLowerCase();
5981
+ const mimeType = file.type.toLowerCase();
5982
+ if (extension === "pdf" || mimeType === "application/pdf") {
5983
+ return /* @__PURE__ */ jsx35(FilePdfIcon, { size: 20, className: "text-red-500" });
5845
5984
  }
5846
- ));
5847
- AlertDialogOverlayBase.displayName = AlertDialogPrimitive.Overlay.displayName;
5848
- var AlertDialogContentBase = React18.forwardRef(({ className, testid = "alertdialog-content", ...props }, ref) => /* @__PURE__ */ jsxs25(AlertDialogPortalBase, { children: [
5849
- /* @__PURE__ */ jsx35(AlertDialogOverlayBase, {}),
5850
- /* @__PURE__ */ jsx35(
5851
- AlertDialogPrimitive.Content,
5852
- {
5853
- ref,
5854
- className: cn(
5855
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
5856
- className
5857
- ),
5858
- "data-testid": testid,
5859
- ...props
5860
- }
5861
- )
5862
- ] }));
5863
- AlertDialogContentBase.displayName = AlertDialogPrimitive.Content.displayName;
5864
- var AlertDialogHeaderBase = ({
5865
- className,
5866
- ...props
5867
- }) => /* @__PURE__ */ jsx35(
5868
- "div",
5869
- {
5870
- className: cn(
5871
- "flex flex-col space-y-2 text-center sm:text-left",
5872
- className
5873
- ),
5874
- ...props
5985
+ if (["doc", "docx"].includes(extension) || mimeType.includes("word")) {
5986
+ return /* @__PURE__ */ jsx35(FileDocIcon, { size: 20, className: "text-blue-500" });
5875
5987
  }
5876
- );
5877
- AlertDialogHeaderBase.displayName = "AlertDialogHeaderBase";
5878
- var AlertDialogFooterBase = ({
5879
- className,
5880
- ...props
5881
- }) => /* @__PURE__ */ jsx35(
5882
- "div",
5883
- {
5884
- className: cn(
5885
- "flex flex-col-reverse sm:flex-row sm:justify-end",
5886
- className
5887
- ),
5888
- ...props
5988
+ if (["xls", "xlsx"].includes(extension) || mimeType.includes("sheet")) {
5989
+ return /* @__PURE__ */ jsx35(FileXlsIcon, { size: 20, className: "text-green-500" });
5889
5990
  }
5890
- );
5891
- AlertDialogFooterBase.displayName = "AlertDialogFooterBase";
5892
- var AlertDialogTitleBase = React18.forwardRef(({ className, testid = "alertdialog-title", ...props }, ref) => /* @__PURE__ */ jsx35(
5893
- AlertDialogPrimitive.Title,
5894
- {
5895
- ref,
5896
- className: cn("text-lg font-semibold", className),
5897
- "data-testid": testid,
5898
- ...props
5991
+ if (["ppt", "pptx"].includes(extension) || mimeType.includes("presentation")) {
5992
+ return /* @__PURE__ */ jsx35(FilePptIcon, { size: 20, className: "text-orange-500" });
5899
5993
  }
5900
- ));
5901
- AlertDialogTitleBase.displayName = AlertDialogPrimitive.Title.displayName;
5902
- var AlertDialogDescriptionBase = React18.forwardRef(({ className, testid = "alertdialog-description", ...props }, ref) => /* @__PURE__ */ jsx35(
5903
- AlertDialogPrimitive.Description,
5904
- {
5905
- ref,
5906
- className: cn("text-sm text-muted-foreground", className),
5907
- "data-testid": testid,
5908
- ...props
5994
+ if (extension === "csv" || mimeType === "text/csv") {
5995
+ return /* @__PURE__ */ jsx35(FileCsvIcon, { size: 20, className: "text-green-600" });
5909
5996
  }
5910
- ));
5911
- AlertDialogDescriptionBase.displayName = AlertDialogPrimitive.Description.displayName;
5912
- var AlertDialogActionBase = React18.forwardRef(({ className, testid = "alertdialog-action", ...props }, ref) => /* @__PURE__ */ jsx35(
5913
- AlertDialogPrimitive.Action,
5914
- {
5915
- ref,
5916
- className: cn(buttonVariantsBase(), className),
5917
- "data-testid": testid,
5918
- ...props
5997
+ if (["txt", "md", "json", "xml", "js", "ts", "html", "css"].includes(
5998
+ extension
5999
+ ) || mimeType.includes("text")) {
6000
+ return /* @__PURE__ */ jsx35(FileTextIcon, { size: 20, className: "text-gray-500" });
5919
6001
  }
5920
- ));
5921
- AlertDialogActionBase.displayName = AlertDialogPrimitive.Action.displayName;
5922
- var AlertDialogCancelBase = React18.forwardRef(({ className, testid = "alertdialog-cancel", ...props }, ref) => /* @__PURE__ */ jsx35(
5923
- AlertDialogPrimitive.Cancel,
5924
- {
5925
- ref,
5926
- className: cn(buttonVariantsBase({ variant: "outline" }), className),
5927
- "data-testid": testid,
5928
- ...props
6002
+ if (mimeType.startsWith("image/")) {
6003
+ return /* @__PURE__ */ jsx35(FileImageIcon, { size: 20, className: "text-purple-500" });
5929
6004
  }
5930
- ));
5931
- AlertDialogCancelBase.displayName = AlertDialogPrimitive.Cancel.displayName;
5932
-
5933
- // src/components/ui/feedback/DestructiveDialog.tsx
5934
- import { jsx as jsx36, jsxs as jsxs26 } from "react/jsx-runtime";
5935
- var DestructiveDialog = ({
5936
- title,
5937
- description,
5938
- onConfirm,
5939
- onCancel,
5940
- children,
5941
- triggerContent
5942
- }) => {
5943
- const triggerEl = React19.isValidElement(children) ? /* @__PURE__ */ jsx36(AlertDialogTriggerBase, { asChild: true, children }) : /* @__PURE__ */ jsx36(AlertDialogTriggerBase, { children: /* @__PURE__ */ jsx36(ButtonBase, { variant: "destructive", children: triggerContent ?? "Excluir" }) });
5944
- return /* @__PURE__ */ jsxs26(AlertDialogBase, { children: [
5945
- triggerEl,
5946
- /* @__PURE__ */ jsxs26(
5947
- AlertDialogContentBase,
5948
- {
5949
- className: cn("border border-destructive bg-background"),
5950
- children: [
5951
- /* @__PURE__ */ jsxs26("div", { className: "flex items-start gap-4", children: [
5952
- /* @__PURE__ */ jsx36("div", { className: "flex items-center justify-center w-10 h-10 rounded-full ring-1 ring-destructive/30", children: /* @__PURE__ */ jsx36(XCircleIcon, { className: "w-6 h-6 text-destructive" }) }),
5953
- /* @__PURE__ */ jsxs26("div", { className: "flex-1", children: [
5954
- /* @__PURE__ */ jsx36(AlertDialogTitleBase, { className: "text-lg sm:text-xl font-semibold text-destructive", children: title }),
5955
- /* @__PURE__ */ jsx36(AlertDialogDescriptionBase, { className: "mt-2 text-sm text-muted-foreground", children: description })
5956
- ] })
5957
- ] }),
5958
- /* @__PURE__ */ jsxs26(AlertDialogFooterBase, { className: "mt-2 flex justify-end gap-3", children: [
5959
- /* @__PURE__ */ jsx36(
5960
- AlertDialogCancelBase,
5961
- {
5962
- onClick: onCancel,
5963
- className: cn(
5964
- buttonVariantsBase({ variant: "outline", size: "default" }),
5965
- "hover:bg-foreground/5 hover:text-primary hover:opacity-90 hover:shadow-none"
5966
- ),
5967
- children: "Cancelar"
5968
- }
5969
- ),
5970
- /* @__PURE__ */ jsx36(
5971
- AlertDialogActionBase,
5972
- {
5973
- onClick: onConfirm,
5974
- className: cn(
5975
- buttonVariantsBase({ variant: "destructive", size: "default" })
5976
- ),
5977
- children: "Confirmar"
5978
- }
5979
- )
5980
- ] })
5981
- ]
5982
- }
5983
- )
5984
- ] });
6005
+ if (mimeType.startsWith("video/")) {
6006
+ return /* @__PURE__ */ jsx35(FileVideoIcon, { size: 20, className: "text-pink-500" });
6007
+ }
6008
+ if (mimeType.startsWith("audio/")) {
6009
+ return /* @__PURE__ */ jsx35(FileAudioIcon, { size: 20, className: "text-indigo-500" });
6010
+ }
6011
+ if (["zip", "rar", "7z", "tar", "gz"].includes(extension)) {
6012
+ return /* @__PURE__ */ jsx35(FileZipIcon, { size: 20, className: "text-yellow-600" });
6013
+ }
6014
+ return /* @__PURE__ */ jsx35(FileIcon, { size: 20, className: "text-muted-foreground" });
5985
6015
  };
5986
-
5987
- // src/components/ui/form/SmallButtons.tsx
5988
- import {
5989
- PencilSimpleIcon,
5990
- FloppyDiskIcon,
5991
- PlusIcon as PlusIcon2,
5992
- XIcon as XIcon5,
5993
- TrashIcon as TrashIcon2,
5994
- DownloadSimpleIcon,
5995
- UploadSimpleIcon,
5996
- CopyIcon,
5997
- ArrowClockwiseIcon,
5998
- MagnifyingGlassIcon as MagnifyingGlassIcon2,
5999
- ArrowLeftIcon,
6000
- GearIcon,
6001
- BellIcon,
6002
- DotsThreeIcon as DotsThreeIcon2,
6003
- CheckIcon as CheckIcon6,
6004
- FunnelIcon,
6005
- HeartIcon,
6006
- StarIcon,
6007
- EyeIcon,
6008
- EyeSlashIcon,
6009
- LockIcon,
6010
- LockOpenIcon,
6011
- ArrowsLeftRightIcon
6012
- } from "@phosphor-icons/react";
6013
- import { jsx as jsx37 } from "react/jsx-runtime";
6014
- var EditButton = React20.forwardRef(
6016
+ var createImagePreview = (file) => {
6017
+ return new Promise((resolve) => {
6018
+ if (!file.type.startsWith("image/")) {
6019
+ resolve(null);
6020
+ return;
6021
+ }
6022
+ const reader = new FileReader();
6023
+ reader.onload = (e) => {
6024
+ resolve(e.target?.result);
6025
+ };
6026
+ reader.onerror = () => {
6027
+ resolve(null);
6028
+ };
6029
+ reader.readAsDataURL(file);
6030
+ });
6031
+ };
6032
+ var FileUploader = React18.forwardRef(
6015
6033
  ({
6016
- disabled,
6017
- onClick,
6018
- testid = "button-edit",
6019
6034
  className,
6020
- iconSize = 18,
6021
- iconColor,
6022
- variant = "default",
6023
- size = "icon",
6035
+ accept,
6036
+ maxSize,
6037
+ maxFiles = 1,
6038
+ disabled = false,
6039
+ value = [],
6040
+ onValueChange,
6041
+ onUpload,
6042
+ showPreview = true,
6043
+ dropzoneText = "Arraste arquivos aqui ou clique para selecionar",
6044
+ dropzoneSubtext,
6045
+ animate = true,
6024
6046
  ...props
6025
- }, ref) => /* @__PURE__ */ jsx37(
6026
- ButtonBase,
6027
- {
6028
- ref,
6029
- variant,
6030
- size,
6031
- onClick,
6032
- disabled,
6033
- testid,
6034
- className: cn(
6035
- "transition-all duration-200 ease-in-out group",
6036
- "hover:scale-105",
6037
- "active:scale-95",
6038
- "disabled:hover:scale-100",
6039
- className
6040
- ),
6041
- ...props,
6042
- children: /* @__PURE__ */ jsx37(
6043
- PencilSimpleIcon,
6044
- {
6045
- size: iconSize,
6046
- color: iconColor,
6047
- className: "transition-transform duration-200 group-hover:-rotate-12"
6048
- }
6049
- )
6050
- }
6051
- )
6052
- );
6053
- EditButton.displayName = "EditButton";
6054
- var ChangeButton = React20.forwardRef(
6055
- ({
6056
- disabled,
6057
- onClick,
6058
- testid = "button-edit",
6059
- className,
6060
- iconSize = 18,
6061
- iconColor,
6062
- variant = "default",
6063
- size = "icon",
6064
- ...props
6065
- }, ref) => /* @__PURE__ */ jsx37(
6066
- ButtonBase,
6067
- {
6068
- ref,
6069
- variant,
6070
- size,
6071
- onClick,
6072
- disabled,
6073
- testid,
6074
- className: cn(
6075
- "transition-all duration-200 ease-in-out group",
6076
- "hover:scale-105",
6077
- "active:scale-95",
6078
- "disabled:hover:scale-100",
6079
- className
6080
- ),
6081
- ...props,
6082
- children: /* @__PURE__ */ jsx37(
6083
- ArrowsLeftRightIcon,
6084
- {
6085
- size: iconSize,
6086
- color: iconColor,
6087
- className: "transition-transform duration-200 group-hover:-rotate-180"
6047
+ }, ref) => {
6048
+ const [isDragging, setIsDragging] = React18.useState(false);
6049
+ const [files, setFiles] = React18.useState(value);
6050
+ const inputRef = React18.useRef(null);
6051
+ const dragCounterRef = React18.useRef(0);
6052
+ const multiple = maxFiles > 1;
6053
+ React18.useEffect(() => {
6054
+ setFiles(value);
6055
+ }, [value]);
6056
+ React18.useEffect(() => {
6057
+ return () => {
6058
+ files.forEach((file) => {
6059
+ if (file.preview) {
6060
+ URL.revokeObjectURL(file.preview);
6061
+ }
6062
+ });
6063
+ };
6064
+ }, [files]);
6065
+ const validateFile = (file) => {
6066
+ if (file.size > maxSize) {
6067
+ return `Arquivo muito grande. M\xE1ximo: ${formatFileSize(maxSize)}`;
6068
+ }
6069
+ if (accept.length > 0) {
6070
+ const fileExtension = `.${getFileExtension(file.name)}`;
6071
+ const fileType = file.type;
6072
+ const isAccepted = accept.some((acceptItem) => {
6073
+ if (acceptItem.startsWith(".")) {
6074
+ return fileExtension.toLowerCase() === acceptItem.toLowerCase();
6075
+ }
6076
+ if (acceptItem.endsWith("/*")) {
6077
+ return fileType.startsWith(acceptItem.replace("/*", ""));
6078
+ }
6079
+ return fileType === acceptItem;
6080
+ });
6081
+ if (!isAccepted) {
6082
+ return `Tipo de arquivo n\xE3o permitido. Aceitos: ${accept.join(", ")}`;
6088
6083
  }
6089
- )
6090
- }
6091
- )
6092
- );
6093
- ChangeButton.displayName = "ChangeButton";
6094
- var SaveButton = React20.forwardRef(
6095
- ({
6096
- disabled,
6097
- onClick,
6098
- testid = "button-save",
6099
- className,
6100
- iconSize = 18,
6101
- iconColor,
6102
- variant = "default",
6103
- size = "icon",
6104
- ...props
6105
- }, ref) => /* @__PURE__ */ jsx37(
6106
- ButtonBase,
6107
- {
6108
- ref,
6109
- variant,
6110
- size,
6111
- onClick,
6112
- disabled,
6113
- testid,
6114
- className: cn(
6115
- "transition-all duration-200 ease-in-out group",
6116
- "hover:scale-105",
6117
- "active:scale-95",
6118
- "disabled:hover:scale-100",
6119
- className
6120
- ),
6121
- ...props,
6122
- children: /* @__PURE__ */ jsx37(
6123
- FloppyDiskIcon,
6124
- {
6125
- size: iconSize,
6126
- color: iconColor,
6127
- className: "transition-transform duration-200 group-hover:scale-110"
6084
+ }
6085
+ return null;
6086
+ };
6087
+ const createFileWithPreview = async (file) => {
6088
+ const fileWithPreview = file;
6089
+ fileWithPreview.id = `${file.name}-${Date.now()}-${Math.random()}`;
6090
+ const error = validateFile(file);
6091
+ if (error) {
6092
+ fileWithPreview.error = error;
6093
+ }
6094
+ if (file.type.startsWith("image/")) {
6095
+ try {
6096
+ const preview = await createImagePreview(file);
6097
+ if (preview) {
6098
+ fileWithPreview.preview = preview;
6099
+ }
6100
+ } catch (error2) {
6101
+ console.warn("Erro ao criar preview da imagem:", error2);
6128
6102
  }
6129
- )
6130
- }
6131
- )
6132
- );
6133
- SaveButton.displayName = "SaveButton";
6134
- var AddButton = React20.forwardRef(
6135
- ({
6136
- disabled,
6137
- onClick,
6138
- testid = "button-add",
6139
- className,
6140
- iconSize = 18,
6141
- iconColor,
6142
- variant = "default",
6143
- size = "icon",
6144
- ...props
6145
- }, ref) => /* @__PURE__ */ jsx37(
6146
- ButtonBase,
6147
- {
6148
- ref,
6149
- variant,
6150
- size,
6151
- onClick,
6152
- disabled,
6153
- testid,
6154
- className: cn(
6155
- "transition-all duration-200 ease-in-out",
6156
- "hover:scale-105",
6157
- "active:scale-95",
6158
- "disabled:hover:scale-100",
6159
- className
6160
- ),
6161
- ...props,
6162
- children: /* @__PURE__ */ jsx37(
6163
- PlusIcon2,
6164
- {
6165
- size: iconSize,
6166
- color: iconColor,
6167
- className: "transition-transform duration-300"
6103
+ }
6104
+ return fileWithPreview;
6105
+ };
6106
+ const handleFiles = async (newFiles) => {
6107
+ if (disabled) return;
6108
+ const availableSlots = maxFiles - files.length;
6109
+ const filesToAdd = multiple ? newFiles.slice(0, availableSlots) : [newFiles[0]];
6110
+ const filesWithPreview = await Promise.all(
6111
+ filesToAdd.map((file) => createFileWithPreview(file))
6112
+ );
6113
+ const updatedFiles = multiple ? [...files, ...filesWithPreview] : filesWithPreview;
6114
+ setFiles(updatedFiles);
6115
+ onValueChange(updatedFiles);
6116
+ if (onUpload) {
6117
+ const validFiles = filesWithPreview.filter((f) => !f.error);
6118
+ if (validFiles.length > 0) {
6119
+ try {
6120
+ await onUpload(validFiles);
6121
+ } catch (error) {
6122
+ console.error("Erro no upload:", error);
6123
+ }
6168
6124
  }
6169
- )
6170
- }
6171
- )
6125
+ }
6126
+ };
6127
+ const handleDragEnter = (e) => {
6128
+ e.preventDefault();
6129
+ e.stopPropagation();
6130
+ dragCounterRef.current++;
6131
+ if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
6132
+ setIsDragging(true);
6133
+ }
6134
+ };
6135
+ const handleDragLeave = (e) => {
6136
+ e.preventDefault();
6137
+ e.stopPropagation();
6138
+ dragCounterRef.current--;
6139
+ if (dragCounterRef.current === 0) {
6140
+ setIsDragging(false);
6141
+ }
6142
+ };
6143
+ const handleDragOver = (e) => {
6144
+ e.preventDefault();
6145
+ e.stopPropagation();
6146
+ };
6147
+ const handleDrop = (e) => {
6148
+ e.preventDefault();
6149
+ e.stopPropagation();
6150
+ setIsDragging(false);
6151
+ dragCounterRef.current = 0;
6152
+ if (disabled) return;
6153
+ const droppedFiles = Array.from(e.dataTransfer.files);
6154
+ handleFiles(droppedFiles);
6155
+ };
6156
+ const handleInputChange = (e) => {
6157
+ if (e.target.files) {
6158
+ const selectedFiles = Array.from(e.target.files);
6159
+ handleFiles(selectedFiles);
6160
+ }
6161
+ };
6162
+ const handleRemoveFile = (fileId) => {
6163
+ const fileToRemove = files.find((f) => f.id === fileId);
6164
+ if (fileToRemove?.preview) {
6165
+ URL.revokeObjectURL(fileToRemove.preview);
6166
+ }
6167
+ const updatedFiles = files.filter((f) => f.id !== fileId);
6168
+ setFiles(updatedFiles);
6169
+ onValueChange(updatedFiles);
6170
+ };
6171
+ const handleClick = () => {
6172
+ if (!disabled) {
6173
+ inputRef.current?.click();
6174
+ }
6175
+ };
6176
+ const acceptString = accept.join(",");
6177
+ const defaultSubtext = dropzoneSubtext || `Formatos: ${accept.join(", ")}. M\xE1ximo: ${formatFileSize(maxSize)}`;
6178
+ return /* @__PURE__ */ jsx35("div", { ref, className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsxs25(
6179
+ motion10.div,
6180
+ {
6181
+ className: cn(
6182
+ "relative flex cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed p-10 transition-all duration-300 dark:shadow-black/20",
6183
+ isDragging && "border-primary bg-primary/10 scale-[1.02]",
6184
+ !isDragging && "border-border hover:border-primary/60 hover:bg-muted/50",
6185
+ disabled && "cursor-not-allowed opacity-50 hover:scale-100"
6186
+ ),
6187
+ onDragEnter: handleDragEnter,
6188
+ onDragOver: handleDragOver,
6189
+ onDragLeave: handleDragLeave,
6190
+ onDrop: handleDrop,
6191
+ onClick: handleClick,
6192
+ whileHover: !disabled ? { scale: 1.01 } : void 0,
6193
+ whileTap: !disabled ? { scale: 0.99 } : void 0,
6194
+ animate: isDragging ? {
6195
+ borderColor: `hsl(var(--primary))`,
6196
+ backgroundColor: `hsl(var(--primary) / 0.1)`,
6197
+ scale: 1.02
6198
+ } : {
6199
+ borderColor: `hsl(var(--border))`,
6200
+ backgroundColor: `hsl(var(--background))`,
6201
+ scale: 1
6202
+ },
6203
+ transition: {
6204
+ type: "spring",
6205
+ stiffness: 300,
6206
+ damping: 25,
6207
+ duration: 0.3
6208
+ },
6209
+ children: [
6210
+ /* @__PURE__ */ jsx35(
6211
+ "input",
6212
+ {
6213
+ ref: inputRef,
6214
+ type: "file",
6215
+ className: "hidden",
6216
+ accept: acceptString,
6217
+ multiple,
6218
+ disabled,
6219
+ onChange: handleInputChange
6220
+ }
6221
+ ),
6222
+ /* @__PURE__ */ jsx35(
6223
+ motion10.div,
6224
+ {
6225
+ animate: isDragging ? { scale: 1.2, rotate: 10 } : { scale: 1, rotate: 0 },
6226
+ transition: {
6227
+ type: "spring",
6228
+ stiffness: 300,
6229
+ damping: 20,
6230
+ duration: 0.3
6231
+ },
6232
+ children: /* @__PURE__ */ jsx35(
6233
+ motion10.div,
6234
+ {
6235
+ className: cn(
6236
+ "mb-4 h-16 w-16 text-muted-foreground transition-colors duration-300 drop-shadow-lg flex items-center justify-center",
6237
+ isDragging && "text-primary"
6238
+ ),
6239
+ initial: false,
6240
+ animate: {
6241
+ color: isDragging ? `hsl(var(--primary))` : `hsl(var(--muted-foreground))`
6242
+ },
6243
+ transition: { duration: 0.3 },
6244
+ children: /* @__PURE__ */ jsx35(CloudArrowUpIcon, { size: 64 })
6245
+ }
6246
+ )
6247
+ }
6248
+ ),
6249
+ /* @__PURE__ */ jsx35(
6250
+ motion10.p,
6251
+ {
6252
+ className: "mb-2 text-base font-semibold text-foreground",
6253
+ initial: animate ? { opacity: 0, y: -10 } : false,
6254
+ animate: { opacity: 1, y: 0 },
6255
+ transition: { delay: 0.1 },
6256
+ children: dropzoneText
6257
+ }
6258
+ ),
6259
+ /* @__PURE__ */ jsx35(
6260
+ motion10.p,
6261
+ {
6262
+ className: "text-sm text-muted-foreground",
6263
+ initial: animate ? { opacity: 0, y: -10 } : false,
6264
+ animate: { opacity: 1, y: 0 },
6265
+ transition: { delay: 0.2 },
6266
+ children: defaultSubtext
6267
+ }
6268
+ ),
6269
+ /* @__PURE__ */ jsx35(AnimatePresence8, { children: files.length > 0 && /* @__PURE__ */ jsxs25(
6270
+ motion10.div,
6271
+ {
6272
+ initial: { opacity: 0, scale: 0.8, y: 10 },
6273
+ animate: {
6274
+ opacity: 1,
6275
+ scale: 1,
6276
+ y: 0,
6277
+ backgroundColor: `hsl(var(--primary) / 0.1)`,
6278
+ borderColor: `hsl(var(--primary) / 0.2)`
6279
+ },
6280
+ exit: { opacity: 0, scale: 0.8, y: 10 },
6281
+ className: cn(
6282
+ "mt-4 flex items-center gap-2 rounded-full border px-4 py-2 backdrop-blur-sm bg-primary/20 border-primary/30 shadow-lg"
6283
+ ),
6284
+ transition: { duration: 0.3 },
6285
+ children: [
6286
+ /* @__PURE__ */ jsx35("div", { className: "h-4 w-4 text-primary flex items-center justify-center", children: /* @__PURE__ */ jsx35(CheckIcon6, { size: 16, className: "text-emerald-500" }) }),
6287
+ /* @__PURE__ */ jsxs25(
6288
+ motion10.span,
6289
+ {
6290
+ className: "text-sm font-semibold text-primary",
6291
+ animate: { color: `hsl(var(--primary))` },
6292
+ transition: { duration: 0.3 },
6293
+ children: [
6294
+ files.length,
6295
+ " ",
6296
+ files.length === 1 ? "arquivo selecionado" : "arquivos selecionados"
6297
+ ]
6298
+ }
6299
+ )
6300
+ ]
6301
+ }
6302
+ ) }),
6303
+ showPreview && files.length > 0 && /* @__PURE__ */ jsx35(
6304
+ motion10.div,
6305
+ {
6306
+ className: "mt-6 w-full",
6307
+ initial: animate ? { opacity: 0, y: 10 } : false,
6308
+ animate: { opacity: 1, y: 0 },
6309
+ transition: { delay: 0.3 },
6310
+ children: /* @__PURE__ */ jsxs25("div", { children: [
6311
+ /* @__PURE__ */ jsxs25("h4", { className: "mb-3 text-sm font-medium text-muted-foreground", children: [
6312
+ "Arquivos selecionados (",
6313
+ files.length,
6314
+ "/",
6315
+ maxFiles,
6316
+ ")"
6317
+ ] }),
6318
+ /* @__PURE__ */ jsx35("div", { className: "space-y-2 overflow-y-auto max-h-44", children: /* @__PURE__ */ jsx35(AnimatePresence8, { mode: "popLayout", children: files.map((file, index) => /* @__PURE__ */ jsxs25(
6319
+ motion10.div,
6320
+ {
6321
+ layout: true,
6322
+ initial: animate ? { opacity: 0, x: -20 } : false,
6323
+ animate: { opacity: 1, x: 0 },
6324
+ exit: {
6325
+ opacity: 0,
6326
+ x: -20,
6327
+ transition: { duration: 0.2 }
6328
+ },
6329
+ transition: {
6330
+ delay: animate ? index * 0.05 : 0,
6331
+ layout: { duration: 0.2 }
6332
+ },
6333
+ className: cn(
6334
+ "flex items-center gap-3 rounded-md border p-3 transition-all duration-300",
6335
+ file.error ? "border-destructive/50 bg-destructive/5" : "border-border bg-background/80 hover:bg-muted/50 hover:shadow-md hover:shadow-primary/10 hover:border-primary/30"
6336
+ ),
6337
+ children: [
6338
+ /* @__PURE__ */ jsx35("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center rounded-md bg-muted overflow-hidden", children: file.preview ? (
6339
+ // Preview de imagem
6340
+ /* @__PURE__ */ jsx35(
6341
+ "img",
6342
+ {
6343
+ src: file.preview,
6344
+ alt: file.name,
6345
+ className: "h-full w-full object-cover rounded-md"
6346
+ }
6347
+ )
6348
+ ) : (
6349
+ // Ícone baseado no tipo de arquivo
6350
+ getFileTypeIcon(file)
6351
+ ) }),
6352
+ /* @__PURE__ */ jsxs25("div", { className: "min-w-0 flex-1", children: [
6353
+ /* @__PURE__ */ jsx35(
6354
+ "p",
6355
+ {
6356
+ className: "truncate text-sm font-medium text-foreground",
6357
+ title: `${file.name} (${file.type || "Tipo desconhecido"})`,
6358
+ children: file.name
6359
+ }
6360
+ ),
6361
+ /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
6362
+ /* @__PURE__ */ jsx35("span", { children: formatFileSize(file.size) }),
6363
+ file.type && /* @__PURE__ */ jsxs25(Fragment6, { children: [
6364
+ /* @__PURE__ */ jsx35("span", { children: "\u2022" }),
6365
+ /* @__PURE__ */ jsx35("span", { className: "uppercase", children: getFileExtension(file.name) })
6366
+ ] })
6367
+ ] }),
6368
+ file.error && /* @__PURE__ */ jsx35(
6369
+ motion10.p,
6370
+ {
6371
+ className: "mt-1 text-xs text-destructive",
6372
+ initial: { opacity: 0, y: -5 },
6373
+ animate: { opacity: 1, y: 0 },
6374
+ children: file.error
6375
+ }
6376
+ )
6377
+ ] }),
6378
+ /* @__PURE__ */ jsx35(
6379
+ ButtonBase,
6380
+ {
6381
+ variant: "destructive",
6382
+ size: "icon",
6383
+ onClick: (e) => {
6384
+ e?.stopPropagation();
6385
+ handleRemoveFile(file.id);
6386
+ },
6387
+ className: "",
6388
+ children: /* @__PURE__ */ jsx35(XIcon5, { size: 12 })
6389
+ }
6390
+ )
6391
+ ]
6392
+ },
6393
+ file.id
6394
+ )) }) })
6395
+ ] })
6396
+ }
6397
+ )
6398
+ ]
6399
+ }
6400
+ ) });
6401
+ }
6172
6402
  );
6173
- AddButton.displayName = "AddButton";
6174
- var CloseButton = React20.forwardRef(
6175
- ({
6176
- disabled,
6177
- onClick,
6178
- testid = "button-close",
6179
- className,
6180
- iconSize = 18,
6181
- iconColor,
6182
- variant = "ghost",
6183
- size = "icon",
6184
- ...props
6185
- }, ref) => /* @__PURE__ */ jsx37(
6186
- ButtonBase,
6403
+ FileUploader.displayName = "FileUploader";
6404
+
6405
+ // src/components/ui/feedback/AlertDialogBase.tsx
6406
+ import * as React19 from "react";
6407
+ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
6408
+ import { jsx as jsx36, jsxs as jsxs26 } from "react/jsx-runtime";
6409
+ var AlertDialogBase = AlertDialogPrimitive.Root;
6410
+ var AlertDialogTriggerBase = AlertDialogPrimitive.Trigger;
6411
+ var AlertDialogPortalBase = AlertDialogPrimitive.Portal;
6412
+ var AlertDialogOverlayBase = React19.forwardRef(({ className, testid = "alertdialog-overlay", ...props }, ref) => /* @__PURE__ */ jsx36(
6413
+ AlertDialogPrimitive.Overlay,
6414
+ {
6415
+ className: cn(
6416
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
6417
+ className
6418
+ ),
6419
+ "data-testid": testid,
6420
+ ...props,
6421
+ ref
6422
+ }
6423
+ ));
6424
+ AlertDialogOverlayBase.displayName = AlertDialogPrimitive.Overlay.displayName;
6425
+ var AlertDialogContentBase = React19.forwardRef(({ className, testid = "alertdialog-content", ...props }, ref) => /* @__PURE__ */ jsxs26(AlertDialogPortalBase, { children: [
6426
+ /* @__PURE__ */ jsx36(AlertDialogOverlayBase, {}),
6427
+ /* @__PURE__ */ jsx36(
6428
+ AlertDialogPrimitive.Content,
6187
6429
  {
6188
6430
  ref,
6189
- variant,
6190
- size,
6191
- onClick,
6192
- disabled,
6193
- testid,
6194
6431
  className: cn(
6195
- "transition-all duration-200 ease-in-out",
6196
- "hover:scale-110 hover:rotate-90 hover:bg-destructive/10",
6197
- "active:scale-95 active:rotate-0",
6198
- "disabled:hover:scale-100 disabled:hover:rotate-0",
6432
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
6199
6433
  className
6200
6434
  ),
6201
- ...props,
6202
- children: /* @__PURE__ */ jsx37(
6203
- XIcon5,
6204
- {
6205
- size: iconSize,
6206
- color: iconColor,
6207
- className: "transition-transform duration-300"
6208
- }
6209
- )
6435
+ "data-testid": testid,
6436
+ ...props
6210
6437
  }
6211
6438
  )
6212
- );
6213
- CloseButton.displayName = "CloseButton";
6214
- var DeleteButton = React20.forwardRef(
6215
- ({
6216
- disabled,
6217
- onClick,
6218
- testid = "button-delete",
6219
- className,
6220
- iconSize = 18,
6221
- iconColor,
6222
- variant = "destructive",
6223
- size = "icon",
6224
- destructiveTitle,
6225
- destructiveDescription,
6226
- destructiveOnConfirm,
6227
- destructiveOnCancel,
6228
- destructiveTriggerContent,
6229
- ...props
6230
- }, ref) => {
6231
- const effectiveDestructiveTitle = destructiveTitle ?? props.title;
6232
- const trigger = /* @__PURE__ */ jsx37(
6233
- ButtonBase,
6234
- {
6235
- ref,
6236
- variant,
6237
- size,
6238
- onClick,
6239
- disabled,
6240
- testid,
6241
- className: cn(
6242
- "transition-all duration-200 ease-in-out group",
6243
- "hover:scale-105",
6244
- "active:scale-95",
6245
- "disabled:hover:scale-100",
6246
- className
6247
- ),
6248
- ...props,
6249
- children: /* @__PURE__ */ jsx37(
6250
- TrashIcon2,
6251
- {
6252
- size: iconSize,
6253
- color: iconColor,
6254
- className: "transition-transform duration-200 group-hover:scale-110"
6255
- }
6256
- )
6257
- }
6258
- );
6259
- if (effectiveDestructiveTitle) {
6260
- return /* @__PURE__ */ jsx37(
6261
- DestructiveDialog,
6262
- {
6263
- title: effectiveDestructiveTitle,
6264
- description: destructiveDescription ?? "Essa a\xE7\xE3o \xE9 irrevers\xEDvel.",
6265
- onConfirm: destructiveOnConfirm ?? (() => {
6266
- }),
6267
- onCancel: destructiveOnCancel,
6268
- triggerContent: destructiveTriggerContent,
6269
- children: trigger
6270
- }
6271
- );
6272
- }
6273
- return trigger;
6274
- }
6275
- );
6276
- DeleteButton.displayName = "DeleteButton";
6277
- var DownloadButton = ({
6278
- disabled,
6279
- onClick,
6280
- testid = "button-download",
6439
+ ] }));
6440
+ AlertDialogContentBase.displayName = AlertDialogPrimitive.Content.displayName;
6441
+ var AlertDialogHeaderBase = ({
6442
+ className,
6281
6443
  ...props
6282
- }) => /* @__PURE__ */ jsx37(
6283
- ButtonBase,
6444
+ }) => /* @__PURE__ */ jsx36(
6445
+ "div",
6284
6446
  {
6285
- variant: "outline",
6286
- size: "icon",
6287
- onClick,
6288
- disabled,
6289
- testid,
6290
6447
  className: cn(
6291
- "transition-all duration-200 ease-in-out group",
6292
- "hover:scale-105",
6293
- "active:scale-95",
6294
- "disabled:hover:scale-100"
6448
+ "flex flex-col space-y-2 text-center sm:text-left",
6449
+ className
6295
6450
  ),
6296
- ...props,
6297
- children: /* @__PURE__ */ jsx37(
6298
- DownloadSimpleIcon,
6299
- {
6300
- size: 18,
6301
- className: "transition-transform duration-300 group-hover:translate-y-0.5"
6302
- }
6303
- )
6451
+ ...props
6304
6452
  }
6305
6453
  );
6306
- var UploadButton = ({
6307
- disabled,
6308
- onClick,
6309
- testid = "button-upload",
6454
+ AlertDialogHeaderBase.displayName = "AlertDialogHeaderBase";
6455
+ var AlertDialogFooterBase = ({
6456
+ className,
6310
6457
  ...props
6311
- }) => /* @__PURE__ */ jsx37(
6312
- ButtonBase,
6458
+ }) => /* @__PURE__ */ jsx36(
6459
+ "div",
6313
6460
  {
6314
- variant: "outline",
6315
- size: "icon",
6316
- onClick,
6317
- disabled,
6318
- testid,
6319
6461
  className: cn(
6320
- "transition-all duration-200 ease-in-out group",
6321
- "hover:scale-105",
6322
- "active:scale-95",
6323
- "disabled:hover:scale-100"
6462
+ "flex flex-col-reverse sm:flex-row sm:justify-end",
6463
+ className
6324
6464
  ),
6325
- ...props,
6326
- children: /* @__PURE__ */ jsx37(
6327
- UploadSimpleIcon,
6328
- {
6329
- size: 18,
6330
- className: "transition-transform duration-300 group-hover:-translate-y-0.5"
6331
- }
6332
- )
6465
+ ...props
6333
6466
  }
6334
6467
  );
6335
- var CopyButton = ({
6336
- disabled,
6337
- onClick,
6338
- testid = "button-copy",
6339
- ...props
6340
- }) => /* @__PURE__ */ jsx37(
6341
- ButtonBase,
6468
+ AlertDialogFooterBase.displayName = "AlertDialogFooterBase";
6469
+ var AlertDialogTitleBase = React19.forwardRef(({ className, testid = "alertdialog-title", ...props }, ref) => /* @__PURE__ */ jsx36(
6470
+ AlertDialogPrimitive.Title,
6342
6471
  {
6343
- variant: "ghost",
6344
- size: "icon",
6345
- onClick,
6346
- disabled,
6347
- testid,
6348
- className: cn(
6349
- "transition-all duration-200 ease-in-out group",
6350
- "hover:scale-105",
6351
- "active:scale-90",
6352
- "disabled:hover:scale-100"
6353
- ),
6354
- ...props,
6355
- children: /* @__PURE__ */ jsx37(
6356
- CopyIcon,
6472
+ ref,
6473
+ className: cn("text-lg font-semibold", className),
6474
+ "data-testid": testid,
6475
+ ...props
6476
+ }
6477
+ ));
6478
+ AlertDialogTitleBase.displayName = AlertDialogPrimitive.Title.displayName;
6479
+ var AlertDialogDescriptionBase = React19.forwardRef(({ className, testid = "alertdialog-description", ...props }, ref) => /* @__PURE__ */ jsx36(
6480
+ AlertDialogPrimitive.Description,
6481
+ {
6482
+ ref,
6483
+ className: cn("text-sm text-muted-foreground", className),
6484
+ "data-testid": testid,
6485
+ ...props
6486
+ }
6487
+ ));
6488
+ AlertDialogDescriptionBase.displayName = AlertDialogPrimitive.Description.displayName;
6489
+ var AlertDialogActionBase = React19.forwardRef(({ className, testid = "alertdialog-action", ...props }, ref) => /* @__PURE__ */ jsx36(
6490
+ AlertDialogPrimitive.Action,
6491
+ {
6492
+ ref,
6493
+ className: cn(buttonVariantsBase(), className),
6494
+ "data-testid": testid,
6495
+ ...props
6496
+ }
6497
+ ));
6498
+ AlertDialogActionBase.displayName = AlertDialogPrimitive.Action.displayName;
6499
+ var AlertDialogCancelBase = React19.forwardRef(({ className, testid = "alertdialog-cancel", ...props }, ref) => /* @__PURE__ */ jsx36(
6500
+ AlertDialogPrimitive.Cancel,
6501
+ {
6502
+ ref,
6503
+ className: cn(buttonVariantsBase({ variant: "outline" }), className),
6504
+ "data-testid": testid,
6505
+ ...props
6506
+ }
6507
+ ));
6508
+ AlertDialogCancelBase.displayName = AlertDialogPrimitive.Cancel.displayName;
6509
+
6510
+ // src/components/ui/feedback/DestructiveDialog.tsx
6511
+ import * as React20 from "react";
6512
+ import { XCircleIcon } from "@phosphor-icons/react";
6513
+ import { jsx as jsx37, jsxs as jsxs27 } from "react/jsx-runtime";
6514
+ var DestructiveDialog = ({
6515
+ title,
6516
+ description,
6517
+ onConfirm,
6518
+ onCancel,
6519
+ children,
6520
+ triggerContent
6521
+ }) => {
6522
+ const triggerEl = React20.isValidElement(children) ? /* @__PURE__ */ jsx37(AlertDialogTriggerBase, { asChild: true, children }) : /* @__PURE__ */ jsx37(AlertDialogTriggerBase, { children: /* @__PURE__ */ jsx37(ButtonBase, { variant: "destructive", children: triggerContent ?? "Excluir" }) });
6523
+ return /* @__PURE__ */ jsxs27(AlertDialogBase, { children: [
6524
+ triggerEl,
6525
+ /* @__PURE__ */ jsxs27(
6526
+ AlertDialogContentBase,
6357
6527
  {
6358
- size: 18,
6359
- className: "transition-transform duration-200 group-hover:scale-110"
6528
+ className: cn("border border-destructive bg-background"),
6529
+ children: [
6530
+ /* @__PURE__ */ jsxs27("div", { className: "flex items-start gap-4", children: [
6531
+ /* @__PURE__ */ jsx37("div", { className: "flex items-center justify-center w-10 h-10 rounded-full ring-1 ring-destructive/30", children: /* @__PURE__ */ jsx37(XCircleIcon, { className: "w-6 h-6 text-destructive" }) }),
6532
+ /* @__PURE__ */ jsxs27("div", { className: "flex-1", children: [
6533
+ /* @__PURE__ */ jsx37(AlertDialogTitleBase, { className: "text-lg sm:text-xl font-semibold text-destructive", children: title }),
6534
+ /* @__PURE__ */ jsx37(AlertDialogDescriptionBase, { className: "mt-2 text-sm text-muted-foreground", children: description })
6535
+ ] })
6536
+ ] }),
6537
+ /* @__PURE__ */ jsxs27(AlertDialogFooterBase, { className: "mt-2 flex justify-end gap-3", children: [
6538
+ /* @__PURE__ */ jsx37(
6539
+ AlertDialogCancelBase,
6540
+ {
6541
+ onClick: onCancel,
6542
+ className: cn(
6543
+ buttonVariantsBase({ variant: "outline", size: "default" }),
6544
+ "hover:bg-foreground/5 hover:text-primary hover:opacity-90 hover:shadow-none"
6545
+ ),
6546
+ children: "Cancelar"
6547
+ }
6548
+ ),
6549
+ /* @__PURE__ */ jsx37(
6550
+ AlertDialogActionBase,
6551
+ {
6552
+ onClick: onConfirm,
6553
+ className: cn(
6554
+ buttonVariantsBase({ variant: "destructive", size: "default" })
6555
+ ),
6556
+ children: "Confirmar"
6557
+ }
6558
+ )
6559
+ ] })
6560
+ ]
6360
6561
  }
6361
6562
  )
6563
+ ] });
6564
+ };
6565
+
6566
+ // src/components/ui/feedback/LoadingBase.tsx
6567
+ import * as React21 from "react";
6568
+ import { cva as cva3 } from "class-variance-authority";
6569
+ import { jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
6570
+ var loadingVariants = cva3(
6571
+ "rounded-full border-2 animate-spin border-muted border-t-primary",
6572
+ {
6573
+ variants: {
6574
+ size: {
6575
+ sm: "h-4 w-4",
6576
+ md: "h-6 w-6",
6577
+ lg: "h-8 w-8",
6578
+ xl: "h-12 w-12 border-[3px]"
6579
+ }
6580
+ },
6581
+ defaultVariants: {
6582
+ size: "md"
6583
+ }
6362
6584
  }
6363
6585
  );
6364
- var RefreshButton = ({
6365
- disabled,
6366
- onClick,
6367
- testid = "button-refresh",
6368
- ...props
6369
- }) => /* @__PURE__ */ jsx37(
6370
- ButtonBase,
6586
+ var dotsVariants = cva3(
6587
+ "flex items-center justify-center",
6371
6588
  {
6372
- variant: "ghost",
6373
- size: "icon",
6374
- onClick,
6375
- disabled,
6376
- testid,
6377
- className: cn(
6378
- "transition-all duration-200 ease-in-out group",
6379
- "hover:scale-105",
6380
- "active:scale-95",
6381
- "disabled:hover:scale-100"
6382
- ),
6383
- ...props,
6384
- children: /* @__PURE__ */ jsx37(
6385
- ArrowClockwiseIcon,
6386
- {
6387
- size: 18,
6388
- className: "transition-transform duration-500 group-hover:rotate-180"
6589
+ variants: {
6590
+ size: {
6591
+ sm: "gap-1",
6592
+ md: "gap-1.5",
6593
+ lg: "gap-2",
6594
+ xl: "gap-2.5"
6389
6595
  }
6390
- )
6596
+ },
6597
+ defaultVariants: {
6598
+ size: "md"
6599
+ }
6391
6600
  }
6392
6601
  );
6393
- var SearchButton = ({
6394
- disabled,
6395
- onClick,
6396
- testid = "button-search",
6397
- ...props
6398
- }) => /* @__PURE__ */ jsx37(
6399
- ButtonBase,
6602
+ var dotVariants = cva3(
6603
+ "rounded-full bg-gradient-to-r from-primary to-primary/70 shadow-sm",
6400
6604
  {
6401
- variant: "outline",
6402
- size: "icon",
6403
- onClick,
6404
- disabled,
6405
- testid,
6406
- className: cn(
6407
- "transition-all duration-200 ease-in-out group",
6408
- "hover:scale-105",
6409
- "active:scale-95",
6410
- "disabled:hover:scale-100"
6411
- ),
6412
- ...props,
6413
- children: /* @__PURE__ */ jsx37(
6414
- MagnifyingGlassIcon2,
6415
- {
6416
- size: 18,
6417
- className: "transition-transform duration-200 group-hover:scale-110 group-hover:-rotate-12"
6605
+ variants: {
6606
+ size: {
6607
+ sm: "h-1.5 w-2",
6608
+ md: "h-2.5 w-2.5",
6609
+ lg: "h-2.5 w-3",
6610
+ xl: "h-3.5 w-4"
6418
6611
  }
6419
- )
6612
+ },
6613
+ defaultVariants: {
6614
+ size: "md"
6615
+ }
6420
6616
  }
6421
6617
  );
6422
- var BackButton = ({
6423
- disabled,
6424
- onClick,
6425
- testid = "button-back",
6426
- ...props
6427
- }) => /* @__PURE__ */ jsx37(
6428
- ButtonBase,
6429
- {
6430
- variant: "ghost",
6431
- size: "icon",
6432
- onClick,
6433
- disabled,
6434
- testid,
6435
- className: cn(
6436
- "transition-all duration-200 ease-in-out group",
6437
- "hover:scale-105",
6438
- "active:scale-95",
6439
- "disabled:hover:scale-100"
6440
- ),
6441
- ...props,
6442
- children: /* @__PURE__ */ jsx37(
6443
- ArrowLeftIcon,
6618
+ var LoadingBase = React21.forwardRef(
6619
+ ({ className, size, message, overlay = false, variant = "spinner", ...props }, ref) => {
6620
+ React21.useEffect(() => {
6621
+ const style = document.createElement("style");
6622
+ style.textContent = `
6623
+ @keyframes dotBounce {
6624
+ 0%, 80%, 100% {
6625
+ transform: translateY(0);
6626
+ opacity: 0.8;
6627
+ }
6628
+ 40% {
6629
+ transform: translateY(-8px);
6630
+ opacity: 1;
6631
+ }
6632
+ }
6633
+ `;
6634
+ document.head.appendChild(style);
6635
+ return () => {
6636
+ if (document.head.contains(style)) {
6637
+ document.head.removeChild(style);
6638
+ }
6639
+ };
6640
+ }, []);
6641
+ const renderSpinner = () => {
6642
+ if (variant === "dots") {
6643
+ return /* @__PURE__ */ jsxs28("div", { className: cn(dotsVariants({ size })), "aria-hidden": "true", children: [
6644
+ /* @__PURE__ */ jsx38(
6645
+ "div",
6646
+ {
6647
+ className: cn(dotVariants({ size })),
6648
+ style: {
6649
+ animation: "dotBounce 1.4s ease-in-out infinite",
6650
+ animationDelay: "0ms",
6651
+ transform: "translateY(0px)"
6652
+ }
6653
+ }
6654
+ ),
6655
+ /* @__PURE__ */ jsx38(
6656
+ "div",
6657
+ {
6658
+ className: cn(dotVariants({ size })),
6659
+ style: {
6660
+ animation: "dotBounce 1.4s ease-in-out infinite",
6661
+ animationDelay: "0.16s",
6662
+ transform: "translateY(0px)"
6663
+ }
6664
+ }
6665
+ ),
6666
+ /* @__PURE__ */ jsx38(
6667
+ "div",
6668
+ {
6669
+ className: cn(dotVariants({ size })),
6670
+ style: {
6671
+ animation: "dotBounce 1.4s ease-in-out infinite",
6672
+ animationDelay: "0.32s",
6673
+ transform: "translateY(0px)"
6674
+ }
6675
+ }
6676
+ )
6677
+ ] });
6678
+ }
6679
+ return /* @__PURE__ */ jsx38(
6680
+ "div",
6681
+ {
6682
+ className: cn(loadingVariants({ size })),
6683
+ style: {
6684
+ animation: "spin 1s linear infinite"
6685
+ },
6686
+ "aria-hidden": "true"
6687
+ }
6688
+ );
6689
+ };
6690
+ const loadingContent = /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-4", children: [
6691
+ renderSpinner(),
6692
+ message && /* @__PURE__ */ jsx38("p", { className: "text-sm font-medium text-muted-foreground animate-pulse", children: message })
6693
+ ] });
6694
+ if (overlay) {
6695
+ return /* @__PURE__ */ jsx38(
6696
+ "div",
6697
+ {
6698
+ ref,
6699
+ className: cn(
6700
+ "fixed inset-0 z-50 flex items-center justify-center",
6701
+ "bg-background/80 dark:bg-background/60",
6702
+ "backdrop-blur-md backdrop-saturate-150",
6703
+ "transition-all duration-300 ease-in-out",
6704
+ "animate-in fade-in-0",
6705
+ className
6706
+ ),
6707
+ role: "status",
6708
+ "aria-label": message || "Carregando",
6709
+ ...props,
6710
+ children: /* @__PURE__ */ jsx38("div", { className: cn(
6711
+ "relative p-8 rounded-2xl",
6712
+ "bg-card/90 dark:bg-card/95",
6713
+ "border border-border/50",
6714
+ "shadow-2xl shadow-black/10 dark:shadow-black/30",
6715
+ "backdrop-blur-xl backdrop-saturate-150",
6716
+ "animate-in zoom-in-95 fade-in-0 duration-300",
6717
+ "text-center space-y-4"
6718
+ ), children: loadingContent })
6719
+ }
6720
+ );
6721
+ }
6722
+ return /* @__PURE__ */ jsx38(
6723
+ "div",
6444
6724
  {
6445
- size: 18,
6446
- className: "transition-transform duration-300 group-hover:-translate-x-1"
6725
+ ref,
6726
+ className: cn("flex items-center justify-center", className),
6727
+ role: "status",
6728
+ "aria-label": message || "Carregando",
6729
+ ...props,
6730
+ children: loadingContent
6447
6731
  }
6448
- )
6732
+ );
6449
6733
  }
6450
6734
  );
6451
- var SettingsButton = ({
6452
- disabled,
6453
- onClick,
6454
- testid = "button-settings",
6455
- ...props
6456
- }) => /* @__PURE__ */ jsx37(
6457
- ButtonBase,
6735
+ LoadingBase.displayName = "LoadingBase";
6736
+
6737
+ // src/components/ui/feedback/ModalBase.tsx
6738
+ import * as React22 from "react";
6739
+ import * as DialogPrimitive2 from "@radix-ui/react-dialog";
6740
+ import { XIcon as XIcon6 } from "@phosphor-icons/react";
6741
+ import { jsx as jsx39, jsxs as jsxs29 } from "react/jsx-runtime";
6742
+ var ModalBase = DialogPrimitive2.Root;
6743
+ var ModalTriggerBase = DialogPrimitive2.Trigger;
6744
+ var ModalPortalBase = DialogPrimitive2.Portal;
6745
+ var ModalCloseBase = DialogPrimitive2.Close;
6746
+ var ModalOverlayBase = React22.forwardRef(({ className, testid: dataTestId = "modal-overlay", ...props }, ref) => /* @__PURE__ */ jsx39(
6747
+ DialogPrimitive2.Overlay,
6458
6748
  {
6459
- variant: "ghost",
6460
- size: "icon",
6461
- onClick,
6462
- disabled,
6463
- testid,
6749
+ ref,
6464
6750
  className: cn(
6465
- "transition-all duration-200 ease-in-out group",
6466
- "hover:scale-105",
6467
- "active:scale-95",
6468
- "disabled:hover:scale-100"
6751
+ "fixed inset-0 z-50 bg-black/60 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
6752
+ className
6469
6753
  ),
6470
- ...props,
6471
- children: /* @__PURE__ */ jsx37(
6472
- GearIcon,
6473
- {
6474
- size: 18,
6475
- className: "transition-transform duration-500 group-hover:rotate-90"
6476
- }
6477
- )
6754
+ "data-testid": dataTestId,
6755
+ ...props
6756
+ }
6757
+ ));
6758
+ ModalOverlayBase.displayName = DialogPrimitive2.Overlay.displayName;
6759
+ var ModalContentBase = React22.forwardRef(
6760
+ ({
6761
+ className,
6762
+ children,
6763
+ testid: dataTestId = "modal-content",
6764
+ size = "md",
6765
+ centered = true,
6766
+ backdropBlur = true,
6767
+ ...props
6768
+ }, ref) => {
6769
+ const sizeClass = size === "sm" ? "max-w-md" : size === "lg" ? "max-w-4xl" : size === "full" ? "w-full max-w-[calc(100%-2rem)]" : "max-w-2xl";
6770
+ const positionClass = centered ? "left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%]" : "left-[50%] top-20 translate-x-[-50%] translate-y-0 sm:translate-y-0";
6771
+ return /* @__PURE__ */ jsxs29(ModalPortalBase, { children: [
6772
+ /* @__PURE__ */ jsx39(
6773
+ ModalOverlayBase,
6774
+ {
6775
+ className: cn("bg-black/40", backdropBlur ? "backdrop-blur-sm" : "")
6776
+ }
6777
+ ),
6778
+ /* @__PURE__ */ jsx39(
6779
+ "style",
6780
+ {
6781
+ dangerouslySetInnerHTML: {
6782
+ __html: `
6783
+ @keyframes modal-fade-in { from { opacity: 0 } to { opacity: 1 } }
6784
+ @keyframes modal-fade-out { from { opacity: 1 } to { opacity: 0 } }
6785
+ @keyframes modal-scale-in { from { opacity: 0; transform: translate(-50%, -48%) scale(.98) } to { opacity:1; transform: translate(-50%, -50%) scale(1) } }
6786
+ @keyframes modal-scale-out { from { opacity:1; transform: translate(-50%, -50%) scale(1) } to { opacity: 0; transform: translate(-50%, -48%) scale(.98) } }
6787
+ @keyframes overlay-fade-in { from { opacity: 0 } to { opacity: 1 } }
6788
+ @keyframes overlay-fade-out { from { opacity: 1 } to { opacity: 0 } }
6789
+ .data-[state=open]\\:animate-modal-in { animation: modal-fade-in 220ms cubic-bezier(.16,.84,.24,1) both, modal-scale-in 220ms cubic-bezier(.16,.84,.24,1) both }
6790
+ .data-[state=closed]\\:animate-modal-out { animation: modal-scale-out 160ms cubic-bezier(.16,.84,.24,1) both, modal-fade-out 160ms cubic-bezier(.16,.84,.24,1) both }
6791
+ .data-[state=open]\\:animate-overlay-in { animation: overlay-fade-in 220ms cubic-bezier(.16,.84,.24,1) both }
6792
+ .data-[state=closed]\\:animate-overlay-out { animation: overlay-fade-out 160ms cubic-bezier(.16,.84,.24,1) both }
6793
+ `
6794
+ }
6795
+ }
6796
+ ),
6797
+ /* @__PURE__ */ jsxs29(
6798
+ DialogPrimitive2.Content,
6799
+ {
6800
+ ref,
6801
+ className: cn(
6802
+ "fixed z-50 grid w-full gap-4 border bg-background p-6 shadow-lg sm:rounded-lg max-h-[90dvh] overflow-auto",
6803
+ "data-[state=open]:animate-modal-in data-[state=closed]:animate-modal-out",
6804
+ positionClass,
6805
+ sizeClass,
6806
+ className
6807
+ ),
6808
+ "data-testid": dataTestId,
6809
+ ...props,
6810
+ children: [
6811
+ children,
6812
+ /* @__PURE__ */ jsxs29(DialogPrimitive2.Close, { className: "absolute right-3 top-3 sm:right-4 sm:top-4 rounded-md bg-muted/10 p-1.5 opacity-80 hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none z-10 hover:bg-muted/20 transition-colors", children: [
6813
+ /* @__PURE__ */ jsx39(XIcon6, { className: "h-5 w-5 sm:h-4 sm:w-4 text-foreground" }),
6814
+ /* @__PURE__ */ jsx39("span", { className: "sr-only", children: "Close" })
6815
+ ] })
6816
+ ]
6817
+ }
6818
+ )
6819
+ ] });
6478
6820
  }
6479
6821
  );
6480
- var NotificationButton = ({
6481
- disabled,
6482
- onClick,
6483
- testid = "button-notification",
6484
- ...props
6485
- }) => /* @__PURE__ */ jsx37(
6486
- ButtonBase,
6822
+ ModalContentBase.displayName = DialogPrimitive2.Content.displayName;
6823
+ var ModalHeaderBase = React22.forwardRef(({ className, testid: dataTestId = "modal-header", ...props }, ref) => /* @__PURE__ */ jsx39(
6824
+ "div",
6487
6825
  {
6488
- variant: "ghost",
6489
- size: "icon",
6490
- onClick,
6491
- disabled,
6492
- testid,
6826
+ ref,
6493
6827
  className: cn(
6494
- "transition-all duration-200 ease-in-out group",
6495
- "hover:scale-105",
6496
- "active:scale-95",
6497
- "disabled:hover:scale-100"
6828
+ "flex flex-col space-y-1.5 text-center sm:text-left",
6829
+ className
6498
6830
  ),
6499
- ...props,
6500
- children: /* @__PURE__ */ jsx37(
6501
- BellIcon,
6502
- {
6503
- size: 18,
6504
- className: "transition-transform duration-300 group-hover:scale-110 group-hover:-rotate-12"
6505
- }
6506
- )
6831
+ "data-testid": dataTestId,
6832
+ ...props
6507
6833
  }
6508
- );
6509
- var MoreButton = ({
6510
- disabled,
6511
- onClick,
6512
- testid = "button-more",
6513
- ...props
6514
- }) => /* @__PURE__ */ jsx37(
6515
- ButtonBase,
6834
+ ));
6835
+ ModalHeaderBase.displayName = "ModalHeader";
6836
+ var ModalFooterBase = React22.forwardRef(({ className, testid: dataTestId = "modal-footer", ...props }, ref) => /* @__PURE__ */ jsx39(
6837
+ "div",
6516
6838
  {
6517
- variant: "ghost",
6518
- size: "icon",
6519
- onClick,
6520
- disabled,
6521
- testid,
6839
+ ref,
6522
6840
  className: cn(
6523
- "transition-all duration-200 ease-in-out group",
6524
- "hover:scale-105",
6525
- "active:scale-95",
6526
- "disabled:hover:scale-100"
6841
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
6842
+ className
6527
6843
  ),
6528
- ...props,
6529
- children: /* @__PURE__ */ jsx37(
6530
- DotsThreeIcon2,
6531
- {
6532
- size: 18,
6533
- className: "transition-transform duration-200 group-hover:scale-110"
6534
- }
6535
- )
6844
+ "data-testid": dataTestId,
6845
+ ...props
6536
6846
  }
6537
- );
6538
- var CheckButton = ({
6539
- disabled,
6540
- onClick,
6541
- testid = "button-check",
6542
- ...props
6543
- }) => /* @__PURE__ */ jsx37(
6544
- ButtonBase,
6847
+ ));
6848
+ ModalFooterBase.displayName = "ModalFooter";
6849
+ var ModalTitleBase = React22.forwardRef(({ className, testid: dataTestId = "modal-title", ...props }, ref) => /* @__PURE__ */ jsx39(
6850
+ DialogPrimitive2.Title,
6545
6851
  {
6546
- variant: "default",
6547
- size: "icon",
6548
- onClick,
6549
- disabled,
6550
- testid,
6852
+ ref,
6551
6853
  className: cn(
6552
- "transition-all duration-200 ease-in-out group",
6553
- "hover:scale-110",
6554
- "active:scale-95",
6555
- "disabled:hover:scale-100"
6854
+ "text-lg font-semibold leading-none tracking-tight",
6855
+ className
6556
6856
  ),
6557
- ...props,
6558
- children: /* @__PURE__ */ jsx37(
6559
- CheckIcon6,
6560
- {
6561
- size: 18,
6562
- className: "transition-transform duration-200 group-hover:scale-110"
6563
- }
6564
- )
6857
+ "data-testid": dataTestId,
6858
+ ...props
6565
6859
  }
6566
- );
6567
- var FilterButton = ({
6568
- disabled,
6569
- onClick,
6570
- testid = "button-filter",
6571
- active = false,
6572
- className,
6573
- iconSize = 18,
6574
- iconColor,
6575
- variant,
6576
- size = "icon",
6577
- ...props
6578
- }) => /* @__PURE__ */ jsx37(
6579
- ButtonBase,
6860
+ ));
6861
+ ModalTitleBase.displayName = DialogPrimitive2.Title.displayName;
6862
+ var ModalDescriptionBase = React22.forwardRef(({ className, testid: dataTestId = "modal-description", ...props }, ref) => /* @__PURE__ */ jsx39(
6863
+ DialogPrimitive2.Description,
6580
6864
  {
6581
- variant: variant || (active ? "default" : "outline"),
6582
- size,
6583
- onClick,
6584
- disabled,
6585
- testid,
6586
- className: cn(
6587
- "transition-all duration-200 ease-in-out",
6588
- "hover:scale-105",
6589
- "active:scale-95",
6590
- "disabled:hover:scale-100",
6591
- className
6592
- ),
6593
- ...props,
6594
- children: /* @__PURE__ */ jsx37(
6595
- FunnelIcon,
6596
- {
6597
- size: iconSize,
6598
- color: iconColor,
6599
- weight: active ? "fill" : "regular",
6600
- className: "transition-all duration-200"
6601
- }
6602
- )
6865
+ ref,
6866
+ className: cn("text-sm text-muted-foreground", className),
6867
+ "data-testid": dataTestId,
6868
+ ...props
6869
+ }
6870
+ ));
6871
+ ModalDescriptionBase.displayName = DialogPrimitive2.Description.displayName;
6872
+
6873
+ // src/components/ui/feedback/ProgressBase.tsx
6874
+ import * as React23 from "react";
6875
+ import * as ProgressPrimitive from "@radix-ui/react-progress";
6876
+ import { jsx as jsx40, jsxs as jsxs30 } from "react/jsx-runtime";
6877
+ var ProgressBase = React23.forwardRef(
6878
+ ({
6879
+ className,
6880
+ value: rawValue,
6881
+ label,
6882
+ leftIcon,
6883
+ rightIcon,
6884
+ variant = "bar",
6885
+ segments = 5,
6886
+ steps = [],
6887
+ currentStep = 0,
6888
+ showValue = false,
6889
+ valuePosition = "right",
6890
+ autocolor,
6891
+ plusIndicator,
6892
+ ...props
6893
+ }, ref) => {
6894
+ const value = Number(rawValue || 0);
6895
+ const indicatorWidth = Math.min(value, 100);
6896
+ switch (variant) {
6897
+ case "segments":
6898
+ return /* @__PURE__ */ jsx40(
6899
+ ProgressSegmentsBase,
6900
+ {
6901
+ label,
6902
+ segments,
6903
+ value: value || 0
6904
+ }
6905
+ );
6906
+ case "panels":
6907
+ return /* @__PURE__ */ jsx40(
6908
+ ProgressPanelsBase,
6909
+ {
6910
+ label,
6911
+ steps,
6912
+ currentStep
6913
+ }
6914
+ );
6915
+ case "circles":
6916
+ return /* @__PURE__ */ jsx40(
6917
+ ProgressCirclesBase,
6918
+ {
6919
+ label,
6920
+ steps,
6921
+ currentStep
6922
+ }
6923
+ );
6924
+ case "bar":
6925
+ default:
6926
+ return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1 w-full min-w-[150px]", children: [
6927
+ label && /* @__PURE__ */ jsx40(LabelBase_default, { className: "py-2", children: label }),
6928
+ /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
6929
+ showValue && valuePosition === "left" && /* @__PURE__ */ jsxs30("div", { className: "w-12 text-sm text-right font-extrabold", children: [
6930
+ Math.round(value || 0),
6931
+ "%"
6932
+ ] }),
6933
+ leftIcon && /* @__PURE__ */ jsx40("div", { className: "flex items-center justify-center", children: leftIcon }),
6934
+ /* @__PURE__ */ jsxs30(
6935
+ ProgressPrimitive.Root,
6936
+ {
6937
+ ref,
6938
+ className: cn(
6939
+ " relative h-3 w-full overflow-visible rounded-full bg-muted/80 shadow-inner transition-all ",
6940
+ className
6941
+ ),
6942
+ value,
6943
+ ...props,
6944
+ children: [
6945
+ /* @__PURE__ */ jsx40(
6946
+ ProgressPrimitive.Indicator,
6947
+ {
6948
+ className: cn(
6949
+ "h-full transition-all duration-500 ease-in-out rounded-lg",
6950
+ // quando não usa autocolor, Indicator deve mostrar a cor primária
6951
+ autocolor && autocolor.length >= 2 ? "bg-transparent" : "bg-primary"
6952
+ ),
6953
+ style: { width: `${indicatorWidth}%` }
6954
+ }
6955
+ ),
6956
+ autocolor && Array.isArray(autocolor) && autocolor.length >= 2 && (() => {
6957
+ const [t1Raw, t2Raw] = autocolor;
6958
+ const [t1, t2] = [Number(t1Raw), Number(t2Raw)].sort(
6959
+ (a, b) => a - b
6960
+ );
6961
+ const v = Number(value || 0);
6962
+ let colorClass = "bg-red-500";
6963
+ if (v <= t1) {
6964
+ colorClass = "bg-red-500";
6965
+ } else if (v <= t2) {
6966
+ colorClass = "bg-yellow-500";
6967
+ } else {
6968
+ colorClass = "bg-emerald-500";
6969
+ }
6970
+ return /* @__PURE__ */ jsx40(
6971
+ "div",
6972
+ {
6973
+ "aria-hidden": true,
6974
+ className: cn(
6975
+ "absolute top-0 left-0 h-full transition-all duration-500 ease-in-out rounded-lg",
6976
+ colorClass
6977
+ ),
6978
+ style: { width: `${indicatorWidth}%` }
6979
+ }
6980
+ );
6981
+ })(),
6982
+ plusIndicator && value > 100 && /* @__PURE__ */ jsx40(
6983
+ "div",
6984
+ {
6985
+ "aria-hidden": "true",
6986
+ className: "absolute top-0 bottom-0 w-0.5 bg-black/70 transition-all duration-500 ease-in-out pointer-events-none",
6987
+ style: { left: `100%` },
6988
+ children: value > 115 && /* @__PURE__ */ jsx40("div", { className: "absolute left-full ml-2 top-1/2 -translate-y-1/2 text-xs whitespace-nowrap font-extrabold", children: `+${Math.round(
6989
+ value - 100
6990
+ )}%` })
6991
+ }
6992
+ ),
6993
+ showValue && valuePosition === "inside" && /* @__PURE__ */ jsxs30(
6994
+ "span",
6995
+ {
6996
+ className: "absolute inset-0 flex items-center justify-center text-sm select-none pointer-events-none text-secondary font-extrabold",
6997
+ "aria-hidden": true,
6998
+ children: [
6999
+ Math.round(value || 0),
7000
+ "%"
7001
+ ]
7002
+ }
7003
+ )
7004
+ ]
7005
+ }
7006
+ ),
7007
+ showValue && valuePosition === "right" && /* @__PURE__ */ jsxs30("div", { className: "w-12 text-sm font-extrabold text-left", children: [
7008
+ Math.round(value || 0),
7009
+ "%"
7010
+ ] }),
7011
+ rightIcon && /* @__PURE__ */ jsx40("div", { className: "flex items-center justify-center", children: rightIcon })
7012
+ ] })
7013
+ ] });
7014
+ }
6603
7015
  }
6604
7016
  );
6605
- var LikeButton = ({
6606
- disabled,
6607
- onClick,
6608
- testid = "button-like",
6609
- isLiked = false,
6610
- className,
6611
- iconSize = 18,
6612
- iconColor,
6613
- variant = "ghost",
6614
- size = "icon",
6615
- ...props
6616
- }) => /* @__PURE__ */ jsx37(
6617
- ButtonBase,
6618
- {
6619
- variant,
6620
- size,
6621
- onClick,
6622
- disabled,
6623
- testid,
6624
- className: cn(
6625
- "transition-all duration-200 ease-in-out group",
6626
- "hover:scale-110",
6627
- "active:scale-95",
6628
- "disabled:hover:scale-100",
6629
- !iconColor && (isLiked ? "text-red-500 dark:text-red-400 hover:text-red-600 dark:hover:text-red-300" : "hover:text-red-500 dark:hover:text-red-400"),
6630
- className
6631
- ),
6632
- ...props,
6633
- children: /* @__PURE__ */ jsx37(
6634
- HeartIcon,
7017
+ ProgressBase.displayName = "ProgressBase";
7018
+ var ProgressSegmentsBase = ({
7019
+ label,
7020
+ segments,
7021
+ value
7022
+ }) => {
7023
+ const filled = Math.round(value / 100 * segments);
7024
+ return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1 w-full min-w-[150px]", children: [
7025
+ label && /* @__PURE__ */ jsx40(LabelBase_default, { className: "py-2", children: label }),
7026
+ /* @__PURE__ */ jsx40("div", { className: "flex gap-1 w-full", children: Array.from({ length: segments }).map((_, idx) => /* @__PURE__ */ jsx40(
7027
+ "div",
6635
7028
  {
6636
- size: iconSize,
6637
- color: iconColor,
6638
- weight: isLiked ? "fill" : "regular",
6639
- className: "transition-all duration-300 group-hover:scale-110"
6640
- }
6641
- )
6642
- }
6643
- );
6644
- var FavoriteButton = ({
6645
- disabled,
6646
- onClick,
6647
- testid = "button-favorite",
6648
- isFavorite = false,
6649
- className,
6650
- iconSize = 18,
6651
- iconColor,
6652
- variant = "ghost",
6653
- size = "icon",
6654
- ...props
6655
- }) => /* @__PURE__ */ jsx37(
6656
- ButtonBase,
7029
+ className: cn(
7030
+ "h-2 flex-1 rounded-full transition-all duration-300",
7031
+ idx < filled ? "bg-primary" : "bg-zinc-300 hover:bg-zinc-400"
7032
+ )
7033
+ },
7034
+ idx
7035
+ )) })
7036
+ ] });
7037
+ };
7038
+ var ArrowRightIcon = () => /* @__PURE__ */ jsx40(
7039
+ "svg",
6657
7040
  {
6658
- variant,
6659
- size,
6660
- onClick,
6661
- disabled,
6662
- testid,
6663
- className: cn(
6664
- "transition-all duration-200 ease-in-out group",
6665
- "hover:scale-110",
6666
- "active:scale-95",
6667
- "disabled:hover:scale-100",
6668
- !iconColor && (isFavorite ? "text-yellow-500 dark:text-yellow-400 hover:text-yellow-600 dark:hover:text-yellow-300" : "hover:text-yellow-500 dark:hover:text-yellow-400"),
6669
- className
6670
- ),
6671
- ...props,
6672
- children: /* @__PURE__ */ jsx37(
6673
- StarIcon,
6674
- {
6675
- size: iconSize,
6676
- color: iconColor,
6677
- weight: isFavorite ? "fill" : "regular",
6678
- className: "transition-all duration-300 group-hover:rotate-12"
6679
- }
6680
- )
7041
+ className: "w-6 h-6 text-zinc-400 transition-transform duration-300 group-hover:translate-x-1",
7042
+ fill: "none",
7043
+ stroke: "currentColor",
7044
+ strokeWidth: 2,
7045
+ viewBox: "0 0 24 24",
7046
+ xmlns: "http://www.w3.org/2000/svg",
7047
+ children: /* @__PURE__ */ jsx40("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" })
6681
7048
  }
6682
7049
  );
6683
- var VisibilityButton = ({
6684
- disabled,
6685
- onClick,
6686
- testid = "button-visibility",
6687
- isVisible = true,
7050
+ var ProgressPanelsBase = ({
7051
+ label,
7052
+ steps,
7053
+ currentStep
7054
+ }) => {
7055
+ return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1 w-full", children: [
7056
+ label && /* @__PURE__ */ jsx40(LabelBase_default, { className: "py-2", children: label }),
7057
+ /* @__PURE__ */ jsx40("div", { className: "flex w-full gap-1 rounded-lg overflow-hidden", children: steps.map((step, idx) => {
7058
+ const isActive = idx === currentStep;
7059
+ const isLast = idx === steps.length - 1;
7060
+ return /* @__PURE__ */ jsxs30(React23.Fragment, { children: [
7061
+ /* @__PURE__ */ jsxs30(
7062
+ "div",
7063
+ {
7064
+ className: cn(
7065
+ "relative flex items-center justify-center cursor-pointer select-none rounded-lg border transition-shadow duration-300 ease-in-out",
7066
+ "hover:shadow-md hover:z-10",
7067
+ "aspect-[5/1] min-w-[90px] px-4",
7068
+ isActive ? "bg-primary/20 border-2 border-primary shadow-lg font-semibold" : "border-zinc-300"
7069
+ ),
7070
+ style: { flex: "1 1 0" },
7071
+ children: [
7072
+ /* @__PURE__ */ jsx40("span", { className: "truncate", children: step }),
7073
+ isActive && /* @__PURE__ */ jsx40("div", { className: "absolute bottom-0 left-0 h-1 w-full animate-pulse rounded-b-lg" })
7074
+ ]
7075
+ }
7076
+ ),
7077
+ !isLast && /* @__PURE__ */ jsx40("div", { className: "flex items-center px-2 group", children: /* @__PURE__ */ jsx40(ArrowRightIcon, {}) })
7078
+ ] }, idx);
7079
+ }) })
7080
+ ] });
7081
+ };
7082
+ var ProgressCirclesBase = ({
7083
+ label,
7084
+ steps,
7085
+ currentStep
7086
+ }) => {
7087
+ return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-2 w-full", children: [
7088
+ label && /* @__PURE__ */ jsx40("label", { className: "py-2 text-base font-semibold text-gray-700 dark:text-gray-300", children: label }),
7089
+ /* @__PURE__ */ jsxs30("div", { className: "relative flex items-center justify-between w-full", children: [
7090
+ /* @__PURE__ */ jsx40("div", { className: "absolute top-5 left-0 w-full h-1 bg-zinc-200 dark:bg-zinc-700" }),
7091
+ /* @__PURE__ */ jsx40(
7092
+ "div",
7093
+ {
7094
+ className: "absolute top-5 left-0 h-1 bg-primary transition-all duration-300",
7095
+ style: {
7096
+ width: `${currentStep / (steps.length - 1) * 100}%`
7097
+ }
7098
+ }
7099
+ ),
7100
+ steps.map((step, idx) => {
7101
+ const isActive = idx <= currentStep;
7102
+ return /* @__PURE__ */ jsxs30(
7103
+ "div",
7104
+ {
7105
+ className: "relative flex flex-col items-center w-10",
7106
+ style: { zIndex: isActive ? 10 : 1 },
7107
+ children: [
7108
+ /* @__PURE__ */ jsx40(
7109
+ "div",
7110
+ {
7111
+ className: cn(
7112
+ "w-10 h-10 rounded-full flex items-center justify-center font-bold text-sm transition-all duration-300 cursor-pointer select-none",
7113
+ isActive ? "bg-primary text-white dark:text-black shadow-md" : "bg-zinc-200 text-zinc-500 hover:bg-zinc-300 dark:bg-zinc-500 dark:text-black"
7114
+ ),
7115
+ children: idx + 1
7116
+ }
7117
+ ),
7118
+ /* @__PURE__ */ jsx40("span", { className: "text-xs text-center font-medium mt-1 max-w-[80px] break-words", children: step })
7119
+ ]
7120
+ },
7121
+ idx
7122
+ );
7123
+ })
7124
+ ] })
7125
+ ] });
7126
+ };
7127
+
7128
+ // src/components/ui/feedback/SkeletonBase.tsx
7129
+ import { jsx as jsx41 } from "react/jsx-runtime";
7130
+ function SkeletonBase({
6688
7131
  className,
6689
- iconSize = 18,
6690
- iconColor,
6691
- variant = "ghost",
6692
- size = "icon",
6693
7132
  ...props
6694
- }) => /* @__PURE__ */ jsx37(
6695
- ButtonBase,
7133
+ }) {
7134
+ return /* @__PURE__ */ jsx41("div", { className: cn("animate-pulse bg-primary/10", className), ...props });
7135
+ }
7136
+
7137
+ // src/components/ui/feedback/SonnerBase.tsx
7138
+ import {
7139
+ CheckCircleIcon,
7140
+ XCircleIcon as XCircleIcon2,
7141
+ InfoIcon,
7142
+ WarningIcon,
7143
+ SpinnerIcon
7144
+ } from "@phosphor-icons/react";
7145
+ import { Toaster as Sonner, toast as sonnertoast } from "sonner";
7146
+ import { jsx as jsx42 } from "react/jsx-runtime";
7147
+ var iconBaseClass = "w-5 h-auto";
7148
+ var Toaster = ({ testId, ...props }) => {
7149
+ return /* @__PURE__ */ jsx42(
7150
+ Sonner,
7151
+ {
7152
+ className: "toaster group",
7153
+ position: "top-center",
7154
+ toastOptions: {
7155
+ classNames: {
7156
+ toast: `
7157
+ group toast
7158
+ bg-background
7159
+ text-foreground
7160
+ shadow-lg rounded-md
7161
+ border-l-4
7162
+ border-border
7163
+ flex items-center gap-3
7164
+ data-[type=success]:border-l-green-500 data-[type=success]:bg-green-50 data-[type=success]:text-green-800 data-[type=success]:border-green-500
7165
+ data-[type=error]:border-l-red-500 data-[type=error]:bg-red-50 data-[type=error]:text-red-800 data-[type=error]:border-red-500
7166
+ data-[type=WarningIcon]:border-l-yellow-500 data-[type=WarningIcon]:bg-yellow-50 data-[type=WarningIcon]:text-yellow-800 data-[type=WarningIcon]:border-yellow-500
7167
+ data-[type=InfoIcon]:border-l-blue-500 data-[type=InfoIcon]:bg-blue-50 data-[type=InfoIcon]:text-blue-800 data-[type=InfoIcon]:border-blue-500
7168
+ `,
7169
+ description: `
7170
+ text-sm
7171
+ group-[.toast]:text-neutral-600
7172
+ `,
7173
+ actionButton: `
7174
+ ml-auto
7175
+ rounded-md px-3 py-1 text-sm font-semibold
7176
+ bg-neutral-800 text-white
7177
+ hover:bg-neutral-700
7178
+ transition-colors duration-200
7179
+ `,
7180
+ cancelButton: `
7181
+ ml-2
7182
+ rounded-md px-3 py-1 text-sm font-semibold
7183
+ bg-neutral-100 text-neutral-700
7184
+ hover:bg-neutral-200
7185
+ transition-colors duration-200
7186
+ `
7187
+ }
7188
+ },
7189
+ "data-testid": testId,
7190
+ ...props
7191
+ }
7192
+ );
7193
+ };
7194
+ var toast2 = {
7195
+ success: (message) => sonnertoast.success(message, {
7196
+ icon: /* @__PURE__ */ jsx42(CheckCircleIcon, { className: `${iconBaseClass} text-green-600`, weight: "fill" }),
7197
+ className: "sonner-success"
7198
+ }),
7199
+ error: (message) => sonnertoast.error(message, {
7200
+ icon: /* @__PURE__ */ jsx42(XCircleIcon2, { className: `${iconBaseClass} text-red-600`, weight: "fill" }),
7201
+ className: "sonner-error"
7202
+ }),
7203
+ warning: (message) => sonnertoast.warning(message, {
7204
+ icon: /* @__PURE__ */ jsx42(WarningIcon, { className: `${iconBaseClass} text-yellow-600`, weight: "fill" }),
7205
+ className: "sonner-WarningIcon"
7206
+ }),
7207
+ info: (message) => sonnertoast.info(message, {
7208
+ icon: /* @__PURE__ */ jsx42(InfoIcon, { className: `${iconBaseClass} text-blue-600`, weight: "fill" }),
7209
+ className: "sonner-InfoIcon"
7210
+ }),
7211
+ loading: (message) => sonnertoast(message, {
7212
+ icon: /* @__PURE__ */ jsx42(SpinnerIcon, { className: `${iconBaseClass} animate-spin text-neutral-500`, weight: "fill" }),
7213
+ className: "sonner-loading"
7214
+ })
7215
+ };
7216
+
7217
+ // src/components/ui/form/CheckBoxBase.tsx
7218
+ import * as React24 from "react";
7219
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
7220
+ import { CheckIcon as CheckIcon7 } from "@phosphor-icons/react";
7221
+ import { motion as motion11 } from "framer-motion";
7222
+ import { jsx as jsx43 } from "react/jsx-runtime";
7223
+ var CheckboxBase = React24.forwardRef(({ className, testid: dataTestId = "checkbox-base", ...props }, ref) => /* @__PURE__ */ jsx43(
7224
+ CheckboxPrimitive.Root,
6696
7225
  {
6697
- variant,
6698
- size,
6699
- onClick,
6700
- disabled,
6701
- testid,
7226
+ ref,
6702
7227
  className: cn(
6703
- "transition-all duration-200 ease-in-out",
6704
- "hover:scale-105",
6705
- "active:scale-95",
6706
- "disabled:hover:scale-100",
7228
+ "peer h-4 w-4 shrink-0 rounded-md border border-primary shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground transition-colors",
6707
7229
  className
6708
7230
  ),
7231
+ "data-testid": dataTestId,
6709
7232
  ...props,
6710
- children: isVisible ? /* @__PURE__ */ jsx37(
6711
- EyeIcon,
6712
- {
6713
- size: iconSize,
6714
- color: iconColor,
6715
- className: "transition-opacity duration-200"
6716
- }
6717
- ) : /* @__PURE__ */ jsx37(
6718
- EyeSlashIcon,
7233
+ children: /* @__PURE__ */ jsx43(CheckboxPrimitive.Indicator, { asChild: true, children: /* @__PURE__ */ jsx43(
7234
+ motion11.div,
6719
7235
  {
6720
- size: iconSize,
6721
- color: iconColor,
6722
- className: "transition-opacity duration-200"
7236
+ initial: { scale: 0, opacity: 0, rotate: -90 },
7237
+ animate: { scale: 1, opacity: 1, rotate: 0 },
7238
+ exit: { scale: 0, opacity: 0, rotate: 90 },
7239
+ transition: { type: "spring", stiffness: 500, damping: 30 },
7240
+ className: "flex items-center justify-center text-current",
7241
+ children: /* @__PURE__ */ jsx43(CheckIcon7, { className: "h-4 w-4", weight: "bold" })
6723
7242
  }
6724
- )
7243
+ ) })
6725
7244
  }
6726
- );
6727
- var ViewButton = (props) => /* @__PURE__ */ jsx37(VisibilityButton, { isVisible: true, testid: "button-view", ...props });
6728
- var HideButton = (props) => /* @__PURE__ */ jsx37(VisibilityButton, { isVisible: false, testid: "button-hide", ...props });
6729
- var LockButton = ({
6730
- disabled,
6731
- onClick,
6732
- testid = "button-lock",
6733
- isLocked = true,
7245
+ ));
7246
+ CheckboxBase.displayName = CheckboxPrimitive.Root.displayName;
7247
+
7248
+ // src/components/ui/form/CollapsibleBase.tsx
7249
+ import * as React25 from "react";
7250
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
7251
+ import { CaretUpDownIcon } from "@phosphor-icons/react";
7252
+ import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
7253
+ var CollapsibleBase = React25.forwardRef(({ ...props }, ref) => {
7254
+ return /* @__PURE__ */ jsx44(CollapsiblePrimitive.Root, { ref, "data-slot": "collapsible", ...props });
7255
+ });
7256
+ CollapsibleBase.displayName = CollapsiblePrimitive.Root.displayName;
7257
+ var CollapsibleTriggerBase = React25.forwardRef(({ className, children, leftIcon, showCaret = true, ...props }, ref) => {
7258
+ return /* @__PURE__ */ jsxs31(
7259
+ CollapsiblePrimitive.CollapsibleTrigger,
7260
+ {
7261
+ ref,
7262
+ className: cn(
7263
+ "flex w-full items-center justify-between p-3 text-left font-medium transition-all duration-500 ease-[cubic-bezier(0.4,0,0.2,1)] hover:bg-accent hover:text-accent-foreground rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 [&[data-state=open]_.caret-icon]:rotate-180",
7264
+ className
7265
+ ),
7266
+ "data-slot": "collapsible-trigger",
7267
+ ...props,
7268
+ children: [
7269
+ /* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-2", children: [
7270
+ leftIcon && /* @__PURE__ */ jsx44("span", { className: "flex-shrink-0 [&>svg]:size-4", children: leftIcon }),
7271
+ /* @__PURE__ */ jsx44("span", { children })
7272
+ ] }),
7273
+ showCaret && /* @__PURE__ */ jsx44("span", { className: "caret-icon flex-shrink-0 transition-transform duration-500 ease-[cubic-bezier(0.4,0,0.2,1)]", children: /* @__PURE__ */ jsx44(CaretUpDownIcon, { className: "h-4 w-4" }) })
7274
+ ]
7275
+ }
7276
+ );
7277
+ });
7278
+ CollapsibleTriggerBase.displayName = CollapsiblePrimitive.CollapsibleTrigger.displayName;
7279
+ var CollapsibleContentBase = React25.forwardRef(({ className, children, ...props }, ref) => {
7280
+ return /* @__PURE__ */ jsx44(
7281
+ CollapsiblePrimitive.CollapsibleContent,
7282
+ {
7283
+ ref,
7284
+ className: cn(
7285
+ "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
7286
+ className
7287
+ ),
7288
+ "data-slot": "collapsible-content",
7289
+ ...props,
7290
+ children: /* @__PURE__ */ jsx44("div", { className: "pb-3 pt-1", children })
7291
+ }
7292
+ );
7293
+ });
7294
+ CollapsibleContentBase.displayName = CollapsiblePrimitive.CollapsibleContent.displayName;
7295
+
7296
+ // src/components/ui/form/DebounceInput.tsx
7297
+ import { useEffect as useEffect10, useState as useState11 } from "react";
7298
+ import { CircleNotchIcon } from "@phosphor-icons/react";
7299
+ import { jsx as jsx45 } from "react/jsx-runtime";
7300
+
7301
+ // src/components/ui/form/HoverCardBase.tsx
7302
+ import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
7303
+ import { jsx as jsx46 } from "react/jsx-runtime";
7304
+ function HoverCardBase(props) {
7305
+ return /* @__PURE__ */ jsx46(HoverCardPrimitive.Root, { ...props });
7306
+ }
7307
+ function HoverCardTriggerBase(props) {
7308
+ return /* @__PURE__ */ jsx46(HoverCardPrimitive.Trigger, { ...props });
7309
+ }
7310
+ function HoverCardContentBase({
6734
7311
  className,
6735
- iconSize = 18,
6736
- iconColor,
6737
- variant = "ghost",
6738
- size = "icon",
7312
+ align = "center",
7313
+ sideOffset = 4,
6739
7314
  ...props
6740
- }) => /* @__PURE__ */ jsx37(
6741
- ButtonBase,
6742
- {
6743
- variant,
6744
- size,
6745
- onClick,
6746
- disabled,
6747
- testid,
6748
- className: cn(
6749
- "transition-all duration-200 ease-in-out group",
6750
- "hover:scale-105",
6751
- "active:scale-95",
6752
- "disabled:hover:scale-100",
6753
- !iconColor && (isLocked ? "text-red-500 dark:text-red-400 hover:text-red-600 dark:hover:text-red-300" : "text-emerald-500 dark:text-emerald-400 hover:text-emerald-600 dark:hover:text-emerald-300"),
6754
- className
6755
- ),
6756
- ...props,
6757
- children: isLocked ? /* @__PURE__ */ jsx37(
6758
- LockIcon,
6759
- {
6760
- size: iconSize,
6761
- color: iconColor,
6762
- className: "transition-all duration-200 group-hover:scale-110"
6763
- }
6764
- ) : /* @__PURE__ */ jsx37(
6765
- LockOpenIcon,
6766
- {
6767
- size: iconSize,
6768
- color: iconColor,
6769
- className: "transition-all duration-200 group-hover:scale-110"
6770
- }
6771
- )
6772
- }
6773
- );
6774
- var UnlockButton = (props) => /* @__PURE__ */ jsx37(LockButton, { isLocked: false, testid: "button-unlock", ...props });
7315
+ }) {
7316
+ return /* @__PURE__ */ jsx46(HoverCardPrimitive.Portal, { children: /* @__PURE__ */ jsx46(
7317
+ HoverCardPrimitive.Content,
7318
+ {
7319
+ align,
7320
+ sideOffset,
7321
+ className: cn(
7322
+ "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
7323
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
7324
+ "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0",
7325
+ "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95",
7326
+ "data-[side=bottom]:slide-in-from-top-2",
7327
+ "data-[side=left]:slide-in-from-right-2",
7328
+ "data-[side=right]:slide-in-from-left-2",
7329
+ "data-[side=top]:slide-in-from-bottom-2",
7330
+ className
7331
+ ),
7332
+ ...props
7333
+ }
7334
+ ) });
7335
+ }
6775
7336
 
6776
- // src/components/ui/data/FileUploader.tsx
6777
- import { Fragment as Fragment6, jsx as jsx38, jsxs as jsxs27 } from "react/jsx-runtime";
6778
- var formatFileSize = (bytes) => {
6779
- if (bytes === 0) return "0 Bytes";
6780
- const k = 1024;
6781
- const sizes = ["Bytes", "KB", "MB", "GB"];
6782
- const i = Math.floor(Math.log(bytes) / Math.log(k));
6783
- return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
6784
- };
6785
- var getFileExtension = (filename) => {
6786
- return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
6787
- };
6788
- var getFileTypeIcon = (file) => {
6789
- const extension = getFileExtension(file.name).toLowerCase();
6790
- const mimeType = file.type.toLowerCase();
6791
- if (extension === "pdf" || mimeType === "application/pdf") {
6792
- return /* @__PURE__ */ jsx38(FilePdfIcon, { size: 20, className: "text-red-500" });
6793
- }
6794
- if (["doc", "docx"].includes(extension) || mimeType.includes("word")) {
6795
- return /* @__PURE__ */ jsx38(FileDocIcon, { size: 20, className: "text-blue-500" });
6796
- }
6797
- if (["xls", "xlsx"].includes(extension) || mimeType.includes("sheet")) {
6798
- return /* @__PURE__ */ jsx38(FileXlsIcon, { size: 20, className: "text-green-500" });
6799
- }
6800
- if (["ppt", "pptx"].includes(extension) || mimeType.includes("presentation")) {
6801
- return /* @__PURE__ */ jsx38(FilePptIcon, { size: 20, className: "text-orange-500" });
6802
- }
6803
- if (extension === "csv" || mimeType === "text/csv") {
6804
- return /* @__PURE__ */ jsx38(FileCsvIcon, { size: 20, className: "text-green-600" });
6805
- }
6806
- if (["txt", "md", "json", "xml", "js", "ts", "html", "css"].includes(
6807
- extension
6808
- ) || mimeType.includes("text")) {
6809
- return /* @__PURE__ */ jsx38(FileTextIcon, { size: 20, className: "text-gray-500" });
6810
- }
6811
- if (mimeType.startsWith("image/")) {
6812
- return /* @__PURE__ */ jsx38(FileImageIcon, { size: 20, className: "text-purple-500" });
6813
- }
6814
- if (mimeType.startsWith("video/")) {
6815
- return /* @__PURE__ */ jsx38(FileVideoIcon, { size: 20, className: "text-pink-500" });
6816
- }
6817
- if (mimeType.startsWith("audio/")) {
6818
- return /* @__PURE__ */ jsx38(FileAudioIcon, { size: 20, className: "text-indigo-500" });
6819
- }
6820
- if (["zip", "rar", "7z", "tar", "gz"].includes(extension)) {
6821
- return /* @__PURE__ */ jsx38(FileZipIcon, { size: 20, className: "text-yellow-600" });
6822
- }
6823
- return /* @__PURE__ */ jsx38(FileIcon, { size: 20, className: "text-muted-foreground" });
6824
- };
6825
- var createImagePreview = (file) => {
6826
- return new Promise((resolve) => {
6827
- if (!file.type.startsWith("image/")) {
6828
- resolve(null);
6829
- return;
7337
+ // src/components/ui/form/Input-OTP-Base.tsx
7338
+ import * as React26 from "react";
7339
+ import { OTPInput, OTPInputContext } from "input-otp";
7340
+ import { MinusIcon } from "@phosphor-icons/react";
7341
+ import { jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
7342
+ function InputOTPBase({
7343
+ className,
7344
+ containerClassName,
7345
+ ...props
7346
+ }) {
7347
+ return /* @__PURE__ */ jsx47(
7348
+ OTPInput,
7349
+ {
7350
+ "data-slot": "input-otp",
7351
+ containerClassName: cn(
7352
+ "flex items-center gap-2 has-disabled:opacity-50",
7353
+ containerClassName
7354
+ ),
7355
+ className: cn("disabled:cursor-not-allowed", className),
7356
+ ...props
7357
+ }
7358
+ );
7359
+ }
7360
+ function InputOTPGroupBase({ className, ...props }) {
7361
+ return /* @__PURE__ */ jsx47(
7362
+ "div",
7363
+ {
7364
+ "data-slot": "input-otp-group",
7365
+ className: cn("flex items-center", className),
7366
+ ...props
7367
+ }
7368
+ );
7369
+ }
7370
+ function InputOTPSlotBase({
7371
+ index,
7372
+ className,
7373
+ ...props
7374
+ }) {
7375
+ const inputOTPContext = React26.useContext(OTPInputContext);
7376
+ const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
7377
+ return /* @__PURE__ */ jsxs32(
7378
+ "div",
7379
+ {
7380
+ "data-slot": "input-otp-slot",
7381
+ "data-active": isActive,
7382
+ className: cn(
7383
+ "data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]",
7384
+ className
7385
+ ),
7386
+ ...props,
7387
+ children: [
7388
+ char,
7389
+ hasFakeCaret && /* @__PURE__ */ jsx47("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx47("div", { className: "animate-caret-blink bg-foreground h-4 w-px duration-1000" }) })
7390
+ ]
6830
7391
  }
6831
- const reader = new FileReader();
6832
- reader.onload = (e) => {
6833
- resolve(e.target?.result);
6834
- };
6835
- reader.onerror = () => {
6836
- resolve(null);
6837
- };
6838
- reader.readAsDataURL(file);
6839
- });
6840
- };
6841
- var FileUploader = React21.forwardRef(
7392
+ );
7393
+ }
7394
+ function InputOTPSeparatorBase({ ...props }) {
7395
+ return /* @__PURE__ */ jsx47("div", { "data-slot": "input-otp-separator", role: "separator", ...props, children: /* @__PURE__ */ jsx47(MinusIcon, {}) });
7396
+ }
7397
+
7398
+ // src/components/ui/form/SliderBase.tsx
7399
+ import * as React27 from "react";
7400
+ import * as SliderPrimitive from "@radix-ui/react-slider";
7401
+ import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
7402
+ var SlideBase = React27.forwardRef(
6842
7403
  ({
6843
7404
  className,
6844
- accept,
6845
- maxSize,
6846
- maxFiles = 1,
6847
- disabled = false,
6848
- value = [],
6849
- onValueChange,
6850
- onUpload,
6851
- showPreview = true,
6852
- dropzoneText = "Arraste arquivos aqui ou clique para selecionar",
6853
- dropzoneSubtext,
6854
- animate = true,
7405
+ orientation = "horizontal",
7406
+ label,
7407
+ leftIcon,
7408
+ rightIcon,
6855
7409
  ...props
6856
7410
  }, ref) => {
6857
- const [isDragging, setIsDragging] = React21.useState(false);
6858
- const [files, setFiles] = React21.useState(value);
6859
- const inputRef = React21.useRef(null);
6860
- const dragCounterRef = React21.useRef(0);
6861
- const multiple = maxFiles > 1;
6862
- React21.useEffect(() => {
6863
- setFiles(value);
6864
- }, [value]);
6865
- React21.useEffect(() => {
6866
- return () => {
6867
- files.forEach((file) => {
6868
- if (file.preview) {
6869
- URL.revokeObjectURL(file.preview);
6870
- }
6871
- });
6872
- };
6873
- }, [files]);
6874
- const validateFile = (file) => {
6875
- if (file.size > maxSize) {
6876
- return `Arquivo muito grande. M\xE1ximo: ${formatFileSize(maxSize)}`;
6877
- }
6878
- if (accept.length > 0) {
6879
- const fileExtension = `.${getFileExtension(file.name)}`;
6880
- const fileType = file.type;
6881
- const isAccepted = accept.some((acceptItem) => {
6882
- if (acceptItem.startsWith(".")) {
6883
- return fileExtension.toLowerCase() === acceptItem.toLowerCase();
6884
- }
6885
- if (acceptItem.endsWith("/*")) {
6886
- return fileType.startsWith(acceptItem.replace("/*", ""));
6887
- }
6888
- return fileType === acceptItem;
6889
- });
6890
- if (!isAccepted) {
6891
- return `Tipo de arquivo n\xE3o permitido. Aceitos: ${accept.join(", ")}`;
6892
- }
6893
- }
6894
- return null;
6895
- };
6896
- const createFileWithPreview = async (file) => {
6897
- const fileWithPreview = file;
6898
- fileWithPreview.id = `${file.name}-${Date.now()}-${Math.random()}`;
6899
- const error = validateFile(file);
6900
- if (error) {
6901
- fileWithPreview.error = error;
6902
- }
6903
- if (file.type.startsWith("image/")) {
6904
- try {
6905
- const preview = await createImagePreview(file);
6906
- if (preview) {
6907
- fileWithPreview.preview = preview;
6908
- }
6909
- } catch (error2) {
6910
- console.warn("Erro ao criar preview da imagem:", error2);
6911
- }
6912
- }
6913
- return fileWithPreview;
6914
- };
6915
- const handleFiles = async (newFiles) => {
6916
- if (disabled) return;
6917
- const availableSlots = maxFiles - files.length;
6918
- const filesToAdd = multiple ? newFiles.slice(0, availableSlots) : [newFiles[0]];
6919
- const filesWithPreview = await Promise.all(
6920
- filesToAdd.map((file) => createFileWithPreview(file))
6921
- );
6922
- const updatedFiles = multiple ? [...files, ...filesWithPreview] : filesWithPreview;
6923
- setFiles(updatedFiles);
6924
- onValueChange(updatedFiles);
6925
- if (onUpload) {
6926
- const validFiles = filesWithPreview.filter((f) => !f.error);
6927
- if (validFiles.length > 0) {
6928
- try {
6929
- await onUpload(validFiles);
6930
- } catch (error) {
6931
- console.error("Erro no upload:", error);
6932
- }
6933
- }
6934
- }
6935
- };
6936
- const handleDragEnter = (e) => {
6937
- e.preventDefault();
6938
- e.stopPropagation();
6939
- dragCounterRef.current++;
6940
- if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
6941
- setIsDragging(true);
6942
- }
6943
- };
6944
- const handleDragLeave = (e) => {
6945
- e.preventDefault();
6946
- e.stopPropagation();
6947
- dragCounterRef.current--;
6948
- if (dragCounterRef.current === 0) {
6949
- setIsDragging(false);
6950
- }
6951
- };
6952
- const handleDragOver = (e) => {
6953
- e.preventDefault();
6954
- e.stopPropagation();
6955
- };
6956
- const handleDrop = (e) => {
6957
- e.preventDefault();
6958
- e.stopPropagation();
6959
- setIsDragging(false);
6960
- dragCounterRef.current = 0;
6961
- if (disabled) return;
6962
- const droppedFiles = Array.from(e.dataTransfer.files);
6963
- handleFiles(droppedFiles);
6964
- };
6965
- const handleInputChange = (e) => {
6966
- if (e.target.files) {
6967
- const selectedFiles = Array.from(e.target.files);
6968
- handleFiles(selectedFiles);
6969
- }
6970
- };
6971
- const handleRemoveFile = (fileId) => {
6972
- const fileToRemove = files.find((f) => f.id === fileId);
6973
- if (fileToRemove?.preview) {
6974
- URL.revokeObjectURL(fileToRemove.preview);
6975
- }
6976
- const updatedFiles = files.filter((f) => f.id !== fileId);
6977
- setFiles(updatedFiles);
6978
- onValueChange(updatedFiles);
6979
- };
6980
- const handleClick = () => {
6981
- if (!disabled) {
6982
- inputRef.current?.click();
6983
- }
6984
- };
6985
- const acceptString = accept.join(",");
6986
- const defaultSubtext = dropzoneSubtext || `Formatos: ${accept.join(", ")}. M\xE1ximo: ${formatFileSize(maxSize)}`;
6987
- return /* @__PURE__ */ jsx38("div", { ref, className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsxs27(
6988
- motion10.div,
6989
- {
6990
- className: cn(
6991
- "relative flex cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed p-10 transition-all duration-300 dark:shadow-black/20",
6992
- isDragging && "border-primary bg-primary/10 scale-[1.02]",
6993
- !isDragging && "border-border hover:border-primary/60 hover:bg-muted/50",
6994
- disabled && "cursor-not-allowed opacity-50 hover:scale-100"
6995
- ),
6996
- onDragEnter: handleDragEnter,
6997
- onDragOver: handleDragOver,
6998
- onDragLeave: handleDragLeave,
6999
- onDrop: handleDrop,
7000
- onClick: handleClick,
7001
- whileHover: !disabled ? { scale: 1.01 } : void 0,
7002
- whileTap: !disabled ? { scale: 0.99 } : void 0,
7003
- animate: isDragging ? {
7004
- borderColor: `hsl(var(--primary))`,
7005
- backgroundColor: `hsl(var(--primary) / 0.1)`,
7006
- scale: 1.02
7007
- } : {
7008
- borderColor: `hsl(var(--border))`,
7009
- backgroundColor: `hsl(var(--background))`,
7010
- scale: 1
7011
- },
7012
- transition: {
7013
- type: "spring",
7014
- stiffness: 300,
7015
- damping: 25,
7016
- duration: 0.3
7017
- },
7018
- children: [
7019
- /* @__PURE__ */ jsx38(
7020
- "input",
7021
- {
7022
- ref: inputRef,
7023
- type: "file",
7024
- className: "hidden",
7025
- accept: acceptString,
7026
- multiple,
7027
- disabled,
7028
- onChange: handleInputChange
7029
- }
7030
- ),
7031
- /* @__PURE__ */ jsx38(
7032
- motion10.div,
7033
- {
7034
- animate: isDragging ? { scale: 1.2, rotate: 10 } : { scale: 1, rotate: 0 },
7035
- transition: {
7036
- type: "spring",
7037
- stiffness: 300,
7038
- damping: 20,
7039
- duration: 0.3
7040
- },
7041
- children: /* @__PURE__ */ jsx38(
7042
- motion10.div,
7043
- {
7044
- className: cn(
7045
- "mb-4 h-16 w-16 text-muted-foreground transition-colors duration-300 drop-shadow-lg flex items-center justify-center",
7046
- isDragging && "text-primary"
7047
- ),
7048
- initial: false,
7049
- animate: {
7050
- color: isDragging ? `hsl(var(--primary))` : `hsl(var(--muted-foreground))`
7051
- },
7052
- transition: { duration: 0.3 },
7053
- children: /* @__PURE__ */ jsx38(CloudArrowUpIcon, { size: 64 })
7054
- }
7055
- )
7056
- }
7057
- ),
7058
- /* @__PURE__ */ jsx38(
7059
- motion10.p,
7060
- {
7061
- className: "mb-2 text-base font-semibold text-foreground",
7062
- initial: animate ? { opacity: 0, y: -10 } : false,
7063
- animate: { opacity: 1, y: 0 },
7064
- transition: { delay: 0.1 },
7065
- children: dropzoneText
7066
- }
7067
- ),
7068
- /* @__PURE__ */ jsx38(
7069
- motion10.p,
7070
- {
7071
- className: "text-sm text-muted-foreground",
7072
- initial: animate ? { opacity: 0, y: -10 } : false,
7073
- animate: { opacity: 1, y: 0 },
7074
- transition: { delay: 0.2 },
7075
- children: defaultSubtext
7076
- }
7077
- ),
7078
- /* @__PURE__ */ jsx38(AnimatePresence8, { children: files.length > 0 && /* @__PURE__ */ jsxs27(
7079
- motion10.div,
7411
+ const isVertical = orientation === "vertical";
7412
+ return /* @__PURE__ */ jsxs33(
7413
+ "div",
7414
+ {
7415
+ className: cn("flex flex-col gap-1", isVertical ? "h-full " : "w-full"),
7416
+ children: [
7417
+ label && /* @__PURE__ */ jsx48(LabelBase_default, { className: "py-2", children: label }),
7418
+ /* @__PURE__ */ jsxs33(
7419
+ "div",
7080
7420
  {
7081
- initial: { opacity: 0, scale: 0.8, y: 10 },
7082
- animate: {
7083
- opacity: 1,
7084
- scale: 1,
7085
- y: 0,
7086
- backgroundColor: `hsl(var(--primary) / 0.1)`,
7087
- borderColor: `hsl(var(--primary) / 0.2)`
7088
- },
7089
- exit: { opacity: 0, scale: 0.8, y: 10 },
7090
7421
  className: cn(
7091
- "mt-4 flex items-center gap-2 rounded-full border px-4 py-2 backdrop-blur-sm bg-primary/20 border-primary/30 shadow-lg"
7422
+ "flex gap-2",
7423
+ isVertical ? "flex-col h-full" : "flex-row items-center w-full"
7092
7424
  ),
7093
- transition: { duration: 0.3 },
7094
7425
  children: [
7095
- /* @__PURE__ */ jsx38("div", { className: "h-4 w-4 text-primary flex items-center justify-center", children: /* @__PURE__ */ jsx38(CheckIcon7, { size: 16, className: "text-emerald-500" }) }),
7096
- /* @__PURE__ */ jsxs27(
7097
- motion10.span,
7098
- {
7099
- className: "text-sm font-semibold text-primary",
7100
- animate: { color: `hsl(var(--primary))` },
7101
- transition: { duration: 0.3 },
7102
- children: [
7103
- files.length,
7104
- " ",
7105
- files.length === 1 ? "arquivo selecionado" : "arquivos selecionados"
7106
- ]
7107
- }
7108
- )
7109
- ]
7110
- }
7111
- ) }),
7112
- showPreview && files.length > 0 && /* @__PURE__ */ jsx38(
7113
- motion10.div,
7114
- {
7115
- className: "mt-6 w-full",
7116
- initial: animate ? { opacity: 0, y: 10 } : false,
7117
- animate: { opacity: 1, y: 0 },
7118
- transition: { delay: 0.3 },
7119
- children: /* @__PURE__ */ jsxs27("div", { children: [
7120
- /* @__PURE__ */ jsxs27("h4", { className: "mb-3 text-sm font-medium text-muted-foreground", children: [
7121
- "Arquivos selecionados (",
7122
- files.length,
7123
- "/",
7124
- maxFiles,
7125
- ")"
7126
- ] }),
7127
- /* @__PURE__ */ jsx38("div", { className: "space-y-2 overflow-y-auto max-h-44", children: /* @__PURE__ */ jsx38(AnimatePresence8, { mode: "popLayout", children: files.map((file, index) => /* @__PURE__ */ jsxs27(
7128
- motion10.div,
7426
+ leftIcon && /* @__PURE__ */ jsx48("div", { className: "flex items-center justify-center", children: leftIcon }),
7427
+ /* @__PURE__ */ jsxs33(
7428
+ SliderPrimitive.Root,
7129
7429
  {
7130
- layout: true,
7131
- initial: animate ? { opacity: 0, x: -20 } : false,
7132
- animate: { opacity: 1, x: 0 },
7133
- exit: {
7134
- opacity: 0,
7135
- x: -20,
7136
- transition: { duration: 0.2 }
7137
- },
7138
- transition: {
7139
- delay: animate ? index * 0.05 : 0,
7140
- layout: { duration: 0.2 }
7141
- },
7430
+ ref,
7431
+ orientation,
7142
7432
  className: cn(
7143
- "flex items-center gap-3 rounded-md border p-3 transition-all duration-300",
7144
- file.error ? "border-destructive/50 bg-destructive/5" : "border-border bg-background/80 hover:bg-muted/50 hover:shadow-md hover:shadow-primary/10 hover:border-primary/30"
7433
+ "relative flex touch-none select-none items-center",
7434
+ isVertical ? "flex-col h-full" : "flex-row w-full",
7435
+ className
7145
7436
  ),
7437
+ ...props,
7146
7438
  children: [
7147
- /* @__PURE__ */ jsx38("div", { className: "flex h-12 w-12 shrink-0 items-center justify-center rounded-md bg-muted overflow-hidden", children: file.preview ? (
7148
- // Preview de imagem
7149
- /* @__PURE__ */ jsx38(
7150
- "img",
7151
- {
7152
- src: file.preview,
7153
- alt: file.name,
7154
- className: "h-full w-full object-cover rounded-md"
7155
- }
7156
- )
7157
- ) : (
7158
- // Ícone baseado no tipo de arquivo
7159
- getFileTypeIcon(file)
7160
- ) }),
7161
- /* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
7162
- /* @__PURE__ */ jsx38(
7163
- "p",
7164
- {
7165
- className: "truncate text-sm font-medium text-foreground",
7166
- title: `${file.name} (${file.type || "Tipo desconhecido"})`,
7167
- children: file.name
7168
- }
7169
- ),
7170
- /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
7171
- /* @__PURE__ */ jsx38("span", { children: formatFileSize(file.size) }),
7172
- file.type && /* @__PURE__ */ jsxs27(Fragment6, { children: [
7173
- /* @__PURE__ */ jsx38("span", { children: "\u2022" }),
7174
- /* @__PURE__ */ jsx38("span", { className: "uppercase", children: getFileExtension(file.name) })
7175
- ] })
7176
- ] }),
7177
- file.error && /* @__PURE__ */ jsx38(
7178
- motion10.p,
7179
- {
7180
- className: "mt-1 text-xs text-destructive",
7181
- initial: { opacity: 0, y: -5 },
7182
- animate: { opacity: 1, y: 0 },
7183
- children: file.error
7184
- }
7185
- )
7186
- ] }),
7187
- /* @__PURE__ */ jsx38(
7188
- DeleteButton,
7439
+ /* @__PURE__ */ jsx48(
7440
+ SliderPrimitive.Track,
7189
7441
  {
7190
- type: "button",
7191
- variant: "destructive",
7192
- size: "icon",
7193
- onClick: (e) => {
7194
- e?.stopPropagation();
7195
- handleRemoveFile(file.id);
7196
- },
7197
- className: "",
7198
- children: /* @__PURE__ */ jsx38(XIcon6, { size: 12 })
7442
+ className: cn(
7443
+ "relative overflow-hidden bg-primary/20 rounded-full",
7444
+ isVertical ? "w-1.5 h-full" : "h-1.5 w-full"
7445
+ ),
7446
+ children: /* @__PURE__ */ jsx48(
7447
+ SliderPrimitive.Range,
7448
+ {
7449
+ className: cn(
7450
+ "absolute bg-primary",
7451
+ isVertical ? "w-full" : "h-full"
7452
+ )
7453
+ }
7454
+ )
7455
+ }
7456
+ ),
7457
+ /* @__PURE__ */ jsx48(
7458
+ SliderPrimitive.Thumb,
7459
+ {
7460
+ className: cn(
7461
+ "block h-4 w-4 rounded-full border border-primary/70 bg-background shadow-md transition-transform",
7462
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2",
7463
+ "hover:scale-125 active:scale-125"
7464
+ )
7199
7465
  }
7200
7466
  )
7201
7467
  ]
7202
- },
7203
- file.id
7204
- )) }) })
7205
- ] })
7468
+ }
7469
+ ),
7470
+ rightIcon && /* @__PURE__ */ jsx48("div", { className: "flex items-center justify-center", children: rightIcon })
7471
+ ]
7206
7472
  }
7207
7473
  )
7208
7474
  ]
7209
7475
  }
7210
- ) });
7476
+ );
7477
+ }
7478
+ );
7479
+ SlideBase.displayName = "SlideBase";
7480
+
7481
+ // src/components/ui/form/SmallButtons.tsx
7482
+ import * as React28 from "react";
7483
+ import {
7484
+ PencilSimpleIcon,
7485
+ FloppyDiskIcon,
7486
+ PlusIcon as PlusIcon2,
7487
+ XIcon as XIcon7,
7488
+ DownloadSimpleIcon,
7489
+ UploadSimpleIcon,
7490
+ CopyIcon,
7491
+ ArrowClockwiseIcon,
7492
+ MagnifyingGlassIcon as MagnifyingGlassIcon2,
7493
+ ArrowLeftIcon,
7494
+ GearIcon,
7495
+ BellIcon,
7496
+ DotsThreeIcon as DotsThreeIcon2,
7497
+ CheckIcon as CheckIcon8,
7498
+ FunnelIcon,
7499
+ HeartIcon,
7500
+ StarIcon,
7501
+ EyeIcon,
7502
+ EyeSlashIcon,
7503
+ LockIcon,
7504
+ LockOpenIcon,
7505
+ ArrowsLeftRightIcon
7506
+ } from "@phosphor-icons/react";
7507
+ import { jsx as jsx49 } from "react/jsx-runtime";
7508
+ var EditButton = React28.forwardRef(
7509
+ ({
7510
+ disabled,
7511
+ onClick,
7512
+ testid = "button-edit",
7513
+ className,
7514
+ iconSize = 18,
7515
+ iconColor,
7516
+ variant = "default",
7517
+ size = "icon",
7518
+ ...props
7519
+ }, ref) => /* @__PURE__ */ jsx49(
7520
+ ButtonBase,
7521
+ {
7522
+ ref,
7523
+ variant,
7524
+ size,
7525
+ onClick,
7526
+ disabled,
7527
+ testid,
7528
+ className: cn(
7529
+ "transition-all duration-200 ease-in-out group",
7530
+ "hover:scale-105",
7531
+ "active:scale-95",
7532
+ "disabled:hover:scale-100",
7533
+ className
7534
+ ),
7535
+ ...props,
7536
+ children: /* @__PURE__ */ jsx49(
7537
+ PencilSimpleIcon,
7538
+ {
7539
+ size: iconSize,
7540
+ color: iconColor,
7541
+ className: "transition-transform duration-200 group-hover:-rotate-12"
7542
+ }
7543
+ )
7544
+ }
7545
+ )
7546
+ );
7547
+ EditButton.displayName = "EditButton";
7548
+ var ChangeButton = React28.forwardRef(
7549
+ ({
7550
+ disabled,
7551
+ onClick,
7552
+ testid = "button-edit",
7553
+ className,
7554
+ iconSize = 18,
7555
+ iconColor,
7556
+ variant = "default",
7557
+ size = "icon",
7558
+ ...props
7559
+ }, ref) => /* @__PURE__ */ jsx49(
7560
+ ButtonBase,
7561
+ {
7562
+ ref,
7563
+ variant,
7564
+ size,
7565
+ onClick,
7566
+ disabled,
7567
+ testid,
7568
+ className: cn(
7569
+ "transition-all duration-200 ease-in-out group",
7570
+ "hover:scale-105",
7571
+ "active:scale-95",
7572
+ "disabled:hover:scale-100",
7573
+ className
7574
+ ),
7575
+ ...props,
7576
+ children: /* @__PURE__ */ jsx49(
7577
+ ArrowsLeftRightIcon,
7578
+ {
7579
+ size: iconSize,
7580
+ color: iconColor,
7581
+ className: "transition-transform duration-200 group-hover:-rotate-180"
7582
+ }
7583
+ )
7584
+ }
7585
+ )
7586
+ );
7587
+ ChangeButton.displayName = "ChangeButton";
7588
+ var SaveButton = React28.forwardRef(
7589
+ ({
7590
+ disabled,
7591
+ onClick,
7592
+ testid = "button-save",
7593
+ className,
7594
+ iconSize = 18,
7595
+ iconColor,
7596
+ variant = "default",
7597
+ size = "icon",
7598
+ ...props
7599
+ }, ref) => /* @__PURE__ */ jsx49(
7600
+ ButtonBase,
7601
+ {
7602
+ ref,
7603
+ variant,
7604
+ size,
7605
+ onClick,
7606
+ disabled,
7607
+ testid,
7608
+ className: cn(
7609
+ "transition-all duration-200 ease-in-out group",
7610
+ "hover:scale-105",
7611
+ "active:scale-95",
7612
+ "disabled:hover:scale-100",
7613
+ className
7614
+ ),
7615
+ ...props,
7616
+ children: /* @__PURE__ */ jsx49(
7617
+ FloppyDiskIcon,
7618
+ {
7619
+ size: iconSize,
7620
+ color: iconColor,
7621
+ className: "transition-transform duration-200 group-hover:scale-110"
7622
+ }
7623
+ )
7624
+ }
7625
+ )
7626
+ );
7627
+ SaveButton.displayName = "SaveButton";
7628
+ var AddButton = React28.forwardRef(
7629
+ ({
7630
+ disabled,
7631
+ onClick,
7632
+ testid = "button-add",
7633
+ className,
7634
+ iconSize = 18,
7635
+ iconColor,
7636
+ variant = "default",
7637
+ size = "icon",
7638
+ ...props
7639
+ }, ref) => /* @__PURE__ */ jsx49(
7640
+ ButtonBase,
7641
+ {
7642
+ ref,
7643
+ variant,
7644
+ size,
7645
+ onClick,
7646
+ disabled,
7647
+ testid,
7648
+ className: cn(
7649
+ "transition-all duration-200 ease-in-out",
7650
+ "hover:scale-105",
7651
+ "active:scale-95",
7652
+ "disabled:hover:scale-100",
7653
+ className
7654
+ ),
7655
+ ...props,
7656
+ children: /* @__PURE__ */ jsx49(
7657
+ PlusIcon2,
7658
+ {
7659
+ size: iconSize,
7660
+ color: iconColor,
7661
+ className: "transition-transform duration-300"
7662
+ }
7663
+ )
7664
+ }
7665
+ )
7666
+ );
7667
+ AddButton.displayName = "AddButton";
7668
+ var CloseButton = React28.forwardRef(
7669
+ ({
7670
+ disabled,
7671
+ onClick,
7672
+ testid = "button-close",
7673
+ className,
7674
+ iconSize = 18,
7675
+ iconColor,
7676
+ variant = "ghost",
7677
+ size = "icon",
7678
+ ...props
7679
+ }, ref) => /* @__PURE__ */ jsx49(
7680
+ ButtonBase,
7681
+ {
7682
+ ref,
7683
+ variant,
7684
+ size,
7685
+ onClick,
7686
+ disabled,
7687
+ testid,
7688
+ className: cn(
7689
+ "transition-all duration-200 ease-in-out",
7690
+ "hover:scale-110 hover:rotate-90 hover:bg-destructive/10",
7691
+ "active:scale-95 active:rotate-0",
7692
+ "disabled:hover:scale-100 disabled:hover:rotate-0",
7693
+ className
7694
+ ),
7695
+ ...props,
7696
+ children: /* @__PURE__ */ jsx49(
7697
+ XIcon7,
7698
+ {
7699
+ size: iconSize,
7700
+ color: iconColor,
7701
+ className: "transition-transform duration-300"
7702
+ }
7703
+ )
7704
+ }
7705
+ )
7706
+ );
7707
+ CloseButton.displayName = "CloseButton";
7708
+ var DownloadButton = ({
7709
+ disabled,
7710
+ onClick,
7711
+ testid = "button-download",
7712
+ ...props
7713
+ }) => /* @__PURE__ */ jsx49(
7714
+ ButtonBase,
7715
+ {
7716
+ variant: "outline",
7717
+ size: "icon",
7718
+ onClick,
7719
+ disabled,
7720
+ testid,
7721
+ className: cn(
7722
+ "transition-all duration-200 ease-in-out group",
7723
+ "hover:scale-105",
7724
+ "active:scale-95",
7725
+ "disabled:hover:scale-100"
7726
+ ),
7727
+ ...props,
7728
+ children: /* @__PURE__ */ jsx49(
7729
+ DownloadSimpleIcon,
7730
+ {
7731
+ size: 18,
7732
+ className: "transition-transform duration-300 group-hover:translate-y-0.5"
7733
+ }
7734
+ )
7211
7735
  }
7212
7736
  );
7213
- FileUploader.displayName = "FileUploader";
7214
-
7215
- // src/components/ui/feedback/LoadingBase.tsx
7216
- import * as React22 from "react";
7217
- import { cva as cva3 } from "class-variance-authority";
7218
- import { jsx as jsx39, jsxs as jsxs28 } from "react/jsx-runtime";
7219
- var loadingVariants = cva3(
7220
- "rounded-full border-2 animate-spin border-muted border-t-primary",
7737
+ var UploadButton = ({
7738
+ disabled,
7739
+ onClick,
7740
+ testid = "button-upload",
7741
+ ...props
7742
+ }) => /* @__PURE__ */ jsx49(
7743
+ ButtonBase,
7221
7744
  {
7222
- variants: {
7223
- size: {
7224
- sm: "h-4 w-4",
7225
- md: "h-6 w-6",
7226
- lg: "h-8 w-8",
7227
- xl: "h-12 w-12 border-[3px]"
7745
+ variant: "outline",
7746
+ size: "icon",
7747
+ onClick,
7748
+ disabled,
7749
+ testid,
7750
+ className: cn(
7751
+ "transition-all duration-200 ease-in-out group",
7752
+ "hover:scale-105",
7753
+ "active:scale-95",
7754
+ "disabled:hover:scale-100"
7755
+ ),
7756
+ ...props,
7757
+ children: /* @__PURE__ */ jsx49(
7758
+ UploadSimpleIcon,
7759
+ {
7760
+ size: 18,
7761
+ className: "transition-transform duration-300 group-hover:-translate-y-0.5"
7228
7762
  }
7229
- },
7230
- defaultVariants: {
7231
- size: "md"
7232
- }
7763
+ )
7233
7764
  }
7234
7765
  );
7235
- var dotsVariants = cva3(
7236
- "flex items-center justify-center",
7766
+ var CopyButton = ({
7767
+ disabled,
7768
+ onClick,
7769
+ testid = "button-copy",
7770
+ ...props
7771
+ }) => /* @__PURE__ */ jsx49(
7772
+ ButtonBase,
7237
7773
  {
7238
- variants: {
7239
- size: {
7240
- sm: "gap-1",
7241
- md: "gap-1.5",
7242
- lg: "gap-2",
7243
- xl: "gap-2.5"
7774
+ variant: "ghost",
7775
+ size: "icon",
7776
+ onClick,
7777
+ disabled,
7778
+ testid,
7779
+ className: cn(
7780
+ "transition-all duration-200 ease-in-out group",
7781
+ "hover:scale-105",
7782
+ "active:scale-90",
7783
+ "disabled:hover:scale-100"
7784
+ ),
7785
+ ...props,
7786
+ children: /* @__PURE__ */ jsx49(
7787
+ CopyIcon,
7788
+ {
7789
+ size: 18,
7790
+ className: "transition-transform duration-200 group-hover:scale-110"
7244
7791
  }
7245
- },
7246
- defaultVariants: {
7247
- size: "md"
7248
- }
7792
+ )
7249
7793
  }
7250
7794
  );
7251
- var dotVariants = cva3(
7252
- "rounded-full bg-gradient-to-r from-primary to-primary/70 shadow-sm",
7795
+ var RefreshButton = ({
7796
+ disabled,
7797
+ onClick,
7798
+ testid = "button-refresh",
7799
+ ...props
7800
+ }) => /* @__PURE__ */ jsx49(
7801
+ ButtonBase,
7802
+ {
7803
+ variant: "ghost",
7804
+ size: "icon",
7805
+ onClick,
7806
+ disabled,
7807
+ testid,
7808
+ className: cn(
7809
+ "transition-all duration-200 ease-in-out group",
7810
+ "hover:scale-105",
7811
+ "active:scale-95",
7812
+ "disabled:hover:scale-100"
7813
+ ),
7814
+ ...props,
7815
+ children: /* @__PURE__ */ jsx49(
7816
+ ArrowClockwiseIcon,
7817
+ {
7818
+ size: 18,
7819
+ className: "transition-transform duration-500 group-hover:rotate-180"
7820
+ }
7821
+ )
7822
+ }
7823
+ );
7824
+ var SearchButton = ({
7825
+ disabled,
7826
+ onClick,
7827
+ testid = "button-search",
7828
+ ...props
7829
+ }) => /* @__PURE__ */ jsx49(
7830
+ ButtonBase,
7831
+ {
7832
+ variant: "outline",
7833
+ size: "icon",
7834
+ onClick,
7835
+ disabled,
7836
+ testid,
7837
+ className: cn(
7838
+ "transition-all duration-200 ease-in-out group",
7839
+ "hover:scale-105",
7840
+ "active:scale-95",
7841
+ "disabled:hover:scale-100"
7842
+ ),
7843
+ ...props,
7844
+ children: /* @__PURE__ */ jsx49(
7845
+ MagnifyingGlassIcon2,
7846
+ {
7847
+ size: 18,
7848
+ className: "transition-transform duration-200 group-hover:scale-110 group-hover:-rotate-12"
7849
+ }
7850
+ )
7851
+ }
7852
+ );
7853
+ var BackButton = ({
7854
+ disabled,
7855
+ onClick,
7856
+ testid = "button-back",
7857
+ ...props
7858
+ }) => /* @__PURE__ */ jsx49(
7859
+ ButtonBase,
7253
7860
  {
7254
- variants: {
7255
- size: {
7256
- sm: "h-1.5 w-2",
7257
- md: "h-2.5 w-2.5",
7258
- lg: "h-2.5 w-3",
7259
- xl: "h-3.5 w-4"
7861
+ variant: "ghost",
7862
+ size: "icon",
7863
+ onClick,
7864
+ disabled,
7865
+ testid,
7866
+ className: cn(
7867
+ "transition-all duration-200 ease-in-out group",
7868
+ "hover:scale-105",
7869
+ "active:scale-95",
7870
+ "disabled:hover:scale-100"
7871
+ ),
7872
+ ...props,
7873
+ children: /* @__PURE__ */ jsx49(
7874
+ ArrowLeftIcon,
7875
+ {
7876
+ size: 18,
7877
+ className: "transition-transform duration-300 group-hover:-translate-x-1"
7260
7878
  }
7261
- },
7262
- defaultVariants: {
7263
- size: "md"
7264
- }
7879
+ )
7265
7880
  }
7266
7881
  );
7267
- var LoadingBase = React22.forwardRef(
7268
- ({ className, size, message, overlay = false, variant = "spinner", ...props }, ref) => {
7269
- React22.useEffect(() => {
7270
- const style = document.createElement("style");
7271
- style.textContent = `
7272
- @keyframes dotBounce {
7273
- 0%, 80%, 100% {
7274
- transform: translateY(0);
7275
- opacity: 0.8;
7276
- }
7277
- 40% {
7278
- transform: translateY(-8px);
7279
- opacity: 1;
7280
- }
7281
- }
7282
- `;
7283
- document.head.appendChild(style);
7284
- return () => {
7285
- if (document.head.contains(style)) {
7286
- document.head.removeChild(style);
7287
- }
7288
- };
7289
- }, []);
7290
- const renderSpinner = () => {
7291
- if (variant === "dots") {
7292
- return /* @__PURE__ */ jsxs28("div", { className: cn(dotsVariants({ size })), "aria-hidden": "true", children: [
7293
- /* @__PURE__ */ jsx39(
7294
- "div",
7295
- {
7296
- className: cn(dotVariants({ size })),
7297
- style: {
7298
- animation: "dotBounce 1.4s ease-in-out infinite",
7299
- animationDelay: "0ms",
7300
- transform: "translateY(0px)"
7301
- }
7302
- }
7303
- ),
7304
- /* @__PURE__ */ jsx39(
7305
- "div",
7306
- {
7307
- className: cn(dotVariants({ size })),
7308
- style: {
7309
- animation: "dotBounce 1.4s ease-in-out infinite",
7310
- animationDelay: "0.16s",
7311
- transform: "translateY(0px)"
7312
- }
7313
- }
7314
- ),
7315
- /* @__PURE__ */ jsx39(
7316
- "div",
7317
- {
7318
- className: cn(dotVariants({ size })),
7319
- style: {
7320
- animation: "dotBounce 1.4s ease-in-out infinite",
7321
- animationDelay: "0.32s",
7322
- transform: "translateY(0px)"
7323
- }
7324
- }
7325
- )
7326
- ] });
7327
- }
7328
- return /* @__PURE__ */ jsx39(
7329
- "div",
7330
- {
7331
- className: cn(loadingVariants({ size })),
7332
- style: {
7333
- animation: "spin 1s linear infinite"
7334
- },
7335
- "aria-hidden": "true"
7336
- }
7337
- );
7338
- };
7339
- const loadingContent = /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-4", children: [
7340
- renderSpinner(),
7341
- message && /* @__PURE__ */ jsx39("p", { className: "text-sm font-medium text-muted-foreground animate-pulse", children: message })
7342
- ] });
7343
- if (overlay) {
7344
- return /* @__PURE__ */ jsx39(
7345
- "div",
7346
- {
7347
- ref,
7348
- className: cn(
7349
- "fixed inset-0 z-50 flex items-center justify-center",
7350
- "bg-background/80 dark:bg-background/60",
7351
- "backdrop-blur-md backdrop-saturate-150",
7352
- "transition-all duration-300 ease-in-out",
7353
- "animate-in fade-in-0",
7354
- className
7355
- ),
7356
- role: "status",
7357
- "aria-label": message || "Carregando",
7358
- ...props,
7359
- children: /* @__PURE__ */ jsx39("div", { className: cn(
7360
- "relative p-8 rounded-2xl",
7361
- "bg-card/90 dark:bg-card/95",
7362
- "border border-border/50",
7363
- "shadow-2xl shadow-black/10 dark:shadow-black/30",
7364
- "backdrop-blur-xl backdrop-saturate-150",
7365
- "animate-in zoom-in-95 fade-in-0 duration-300",
7366
- "text-center space-y-4"
7367
- ), children: loadingContent })
7368
- }
7369
- );
7370
- }
7371
- return /* @__PURE__ */ jsx39(
7372
- "div",
7882
+ var SettingsButton = ({
7883
+ disabled,
7884
+ onClick,
7885
+ testid = "button-settings",
7886
+ ...props
7887
+ }) => /* @__PURE__ */ jsx49(
7888
+ ButtonBase,
7889
+ {
7890
+ variant: "ghost",
7891
+ size: "icon",
7892
+ onClick,
7893
+ disabled,
7894
+ testid,
7895
+ className: cn(
7896
+ "transition-all duration-200 ease-in-out group",
7897
+ "hover:scale-105",
7898
+ "active:scale-95",
7899
+ "disabled:hover:scale-100"
7900
+ ),
7901
+ ...props,
7902
+ children: /* @__PURE__ */ jsx49(
7903
+ GearIcon,
7373
7904
  {
7374
- ref,
7375
- className: cn("flex items-center justify-center", className),
7376
- role: "status",
7377
- "aria-label": message || "Carregando",
7378
- ...props,
7379
- children: loadingContent
7905
+ size: 18,
7906
+ className: "transition-transform duration-500 group-hover:rotate-90"
7380
7907
  }
7381
- );
7908
+ )
7382
7909
  }
7383
7910
  );
7384
- LoadingBase.displayName = "LoadingBase";
7385
-
7386
- // src/components/ui/feedback/ModalBase.tsx
7387
- import * as React23 from "react";
7388
- import * as DialogPrimitive2 from "@radix-ui/react-dialog";
7389
- import { XIcon as XIcon7 } from "@phosphor-icons/react";
7390
- import { jsx as jsx40, jsxs as jsxs29 } from "react/jsx-runtime";
7391
- var ModalBase = DialogPrimitive2.Root;
7392
- var ModalTriggerBase = DialogPrimitive2.Trigger;
7393
- var ModalPortalBase = DialogPrimitive2.Portal;
7394
- var ModalCloseBase = DialogPrimitive2.Close;
7395
- var ModalOverlayBase = React23.forwardRef(({ className, testid: dataTestId = "modal-overlay", ...props }, ref) => /* @__PURE__ */ jsx40(
7396
- DialogPrimitive2.Overlay,
7911
+ var NotificationButton = ({
7912
+ disabled,
7913
+ onClick,
7914
+ testid = "button-notification",
7915
+ ...props
7916
+ }) => /* @__PURE__ */ jsx49(
7917
+ ButtonBase,
7397
7918
  {
7398
- ref,
7919
+ variant: "ghost",
7920
+ size: "icon",
7921
+ onClick,
7922
+ disabled,
7923
+ testid,
7399
7924
  className: cn(
7400
- "fixed inset-0 z-50 bg-black/60 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
7401
- className
7925
+ "transition-all duration-200 ease-in-out group",
7926
+ "hover:scale-105",
7927
+ "active:scale-95",
7928
+ "disabled:hover:scale-100"
7402
7929
  ),
7403
- "data-testid": dataTestId,
7404
- ...props
7405
- }
7406
- ));
7407
- ModalOverlayBase.displayName = DialogPrimitive2.Overlay.displayName;
7408
- var ModalContentBase = React23.forwardRef(
7409
- ({
7410
- className,
7411
- children,
7412
- testid: dataTestId = "modal-content",
7413
- size = "md",
7414
- centered = true,
7415
- backdropBlur = true,
7416
- ...props
7417
- }, ref) => {
7418
- const sizeClass = size === "sm" ? "max-w-md" : size === "lg" ? "max-w-4xl" : size === "full" ? "w-full max-w-[calc(100%-2rem)]" : "max-w-2xl";
7419
- const positionClass = centered ? "left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%]" : "left-[50%] top-20 translate-x-[-50%] translate-y-0 sm:translate-y-0";
7420
- return /* @__PURE__ */ jsxs29(ModalPortalBase, { children: [
7421
- /* @__PURE__ */ jsx40(
7422
- ModalOverlayBase,
7423
- {
7424
- className: cn("bg-black/40", backdropBlur ? "backdrop-blur-sm" : "")
7425
- }
7426
- ),
7427
- /* @__PURE__ */ jsx40(
7428
- "style",
7429
- {
7430
- dangerouslySetInnerHTML: {
7431
- __html: `
7432
- @keyframes modal-fade-in { from { opacity: 0 } to { opacity: 1 } }
7433
- @keyframes modal-fade-out { from { opacity: 1 } to { opacity: 0 } }
7434
- @keyframes modal-scale-in { from { opacity: 0; transform: translate(-50%, -48%) scale(.98) } to { opacity:1; transform: translate(-50%, -50%) scale(1) } }
7435
- @keyframes modal-scale-out { from { opacity:1; transform: translate(-50%, -50%) scale(1) } to { opacity: 0; transform: translate(-50%, -48%) scale(.98) } }
7436
- @keyframes overlay-fade-in { from { opacity: 0 } to { opacity: 1 } }
7437
- @keyframes overlay-fade-out { from { opacity: 1 } to { opacity: 0 } }
7438
- .data-[state=open]\\:animate-modal-in { animation: modal-fade-in 220ms cubic-bezier(.16,.84,.24,1) both, modal-scale-in 220ms cubic-bezier(.16,.84,.24,1) both }
7439
- .data-[state=closed]\\:animate-modal-out { animation: modal-scale-out 160ms cubic-bezier(.16,.84,.24,1) both, modal-fade-out 160ms cubic-bezier(.16,.84,.24,1) both }
7440
- .data-[state=open]\\:animate-overlay-in { animation: overlay-fade-in 220ms cubic-bezier(.16,.84,.24,1) both }
7441
- .data-[state=closed]\\:animate-overlay-out { animation: overlay-fade-out 160ms cubic-bezier(.16,.84,.24,1) both }
7442
- `
7443
- }
7444
- }
7445
- ),
7446
- /* @__PURE__ */ jsxs29(
7447
- DialogPrimitive2.Content,
7448
- {
7449
- ref,
7450
- className: cn(
7451
- "fixed z-50 grid w-full gap-4 border bg-background p-6 shadow-lg sm:rounded-lg max-h-[90dvh] overflow-auto",
7452
- "data-[state=open]:animate-modal-in data-[state=closed]:animate-modal-out",
7453
- positionClass,
7454
- sizeClass,
7455
- className
7456
- ),
7457
- "data-testid": dataTestId,
7458
- ...props,
7459
- children: [
7460
- children,
7461
- /* @__PURE__ */ jsxs29(DialogPrimitive2.Close, { className: "absolute right-3 top-3 sm:right-4 sm:top-4 rounded-md bg-muted/10 p-1.5 opacity-80 hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none z-10 hover:bg-muted/20 transition-colors", children: [
7462
- /* @__PURE__ */ jsx40(XIcon7, { className: "h-5 w-5 sm:h-4 sm:w-4 text-foreground" }),
7463
- /* @__PURE__ */ jsx40("span", { className: "sr-only", children: "Close" })
7464
- ] })
7465
- ]
7466
- }
7467
- )
7468
- ] });
7930
+ ...props,
7931
+ children: /* @__PURE__ */ jsx49(
7932
+ BellIcon,
7933
+ {
7934
+ size: 18,
7935
+ className: "transition-transform duration-300 group-hover:scale-110 group-hover:-rotate-12"
7936
+ }
7937
+ )
7469
7938
  }
7470
7939
  );
7471
- ModalContentBase.displayName = DialogPrimitive2.Content.displayName;
7472
- var ModalHeaderBase = React23.forwardRef(({ className, testid: dataTestId = "modal-header", ...props }, ref) => /* @__PURE__ */ jsx40(
7473
- "div",
7940
+ var MoreButton = ({
7941
+ disabled,
7942
+ onClick,
7943
+ testid = "button-more",
7944
+ ...props
7945
+ }) => /* @__PURE__ */ jsx49(
7946
+ ButtonBase,
7474
7947
  {
7475
- ref,
7948
+ variant: "ghost",
7949
+ size: "icon",
7950
+ onClick,
7951
+ disabled,
7952
+ testid,
7476
7953
  className: cn(
7477
- "flex flex-col space-y-1.5 text-center sm:text-left",
7478
- className
7954
+ "transition-all duration-200 ease-in-out group",
7955
+ "hover:scale-105",
7956
+ "active:scale-95",
7957
+ "disabled:hover:scale-100"
7479
7958
  ),
7480
- "data-testid": dataTestId,
7481
- ...props
7959
+ ...props,
7960
+ children: /* @__PURE__ */ jsx49(
7961
+ DotsThreeIcon2,
7962
+ {
7963
+ size: 18,
7964
+ className: "transition-transform duration-200 group-hover:scale-110"
7965
+ }
7966
+ )
7482
7967
  }
7483
- ));
7484
- ModalHeaderBase.displayName = "ModalHeader";
7485
- var ModalFooterBase = React23.forwardRef(({ className, testid: dataTestId = "modal-footer", ...props }, ref) => /* @__PURE__ */ jsx40(
7486
- "div",
7968
+ );
7969
+ var CheckButton = ({
7970
+ disabled,
7971
+ onClick,
7972
+ testid = "button-check",
7973
+ ...props
7974
+ }) => /* @__PURE__ */ jsx49(
7975
+ ButtonBase,
7487
7976
  {
7488
- ref,
7977
+ variant: "default",
7978
+ size: "icon",
7979
+ onClick,
7980
+ disabled,
7981
+ testid,
7489
7982
  className: cn(
7490
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
7491
- className
7983
+ "transition-all duration-200 ease-in-out group",
7984
+ "hover:scale-110",
7985
+ "active:scale-95",
7986
+ "disabled:hover:scale-100"
7492
7987
  ),
7493
- "data-testid": dataTestId,
7494
- ...props
7988
+ ...props,
7989
+ children: /* @__PURE__ */ jsx49(
7990
+ CheckIcon8,
7991
+ {
7992
+ size: 18,
7993
+ className: "transition-transform duration-200 group-hover:scale-110"
7994
+ }
7995
+ )
7495
7996
  }
7496
- ));
7497
- ModalFooterBase.displayName = "ModalFooter";
7498
- var ModalTitleBase = React23.forwardRef(({ className, testid: dataTestId = "modal-title", ...props }, ref) => /* @__PURE__ */ jsx40(
7499
- DialogPrimitive2.Title,
7997
+ );
7998
+ var FilterButton = ({
7999
+ disabled,
8000
+ onClick,
8001
+ testid = "button-filter",
8002
+ active = false,
8003
+ className,
8004
+ iconSize = 18,
8005
+ iconColor,
8006
+ variant,
8007
+ size = "icon",
8008
+ ...props
8009
+ }) => /* @__PURE__ */ jsx49(
8010
+ ButtonBase,
7500
8011
  {
7501
- ref,
8012
+ variant: variant || (active ? "default" : "outline"),
8013
+ size,
8014
+ onClick,
8015
+ disabled,
8016
+ testid,
7502
8017
  className: cn(
7503
- "text-lg font-semibold leading-none tracking-tight",
8018
+ "transition-all duration-200 ease-in-out",
8019
+ "hover:scale-105",
8020
+ "active:scale-95",
8021
+ "disabled:hover:scale-100",
7504
8022
  className
7505
8023
  ),
7506
- "data-testid": dataTestId,
7507
- ...props
8024
+ ...props,
8025
+ children: /* @__PURE__ */ jsx49(
8026
+ FunnelIcon,
8027
+ {
8028
+ size: iconSize,
8029
+ color: iconColor,
8030
+ weight: active ? "fill" : "regular",
8031
+ className: "transition-all duration-200"
8032
+ }
8033
+ )
7508
8034
  }
7509
- ));
7510
- ModalTitleBase.displayName = DialogPrimitive2.Title.displayName;
7511
- var ModalDescriptionBase = React23.forwardRef(({ className, testid: dataTestId = "modal-description", ...props }, ref) => /* @__PURE__ */ jsx40(
7512
- DialogPrimitive2.Description,
8035
+ );
8036
+ var LikeButton = ({
8037
+ disabled,
8038
+ onClick,
8039
+ testid = "button-like",
8040
+ isLiked = false,
8041
+ className,
8042
+ iconSize = 18,
8043
+ iconColor,
8044
+ variant = "ghost",
8045
+ size = "icon",
8046
+ ...props
8047
+ }) => /* @__PURE__ */ jsx49(
8048
+ ButtonBase,
7513
8049
  {
7514
- ref,
7515
- className: cn("text-sm text-muted-foreground", className),
7516
- "data-testid": dataTestId,
7517
- ...props
7518
- }
7519
- ));
7520
- ModalDescriptionBase.displayName = DialogPrimitive2.Description.displayName;
7521
-
7522
- // src/components/ui/feedback/ProgressBase.tsx
7523
- import * as React24 from "react";
7524
- import * as ProgressPrimitive from "@radix-ui/react-progress";
7525
- import { jsx as jsx41, jsxs as jsxs30 } from "react/jsx-runtime";
7526
- var ProgressBase = React24.forwardRef(
7527
- ({
7528
- className,
7529
- value: rawValue,
7530
- label,
7531
- leftIcon,
7532
- rightIcon,
7533
- variant = "bar",
7534
- segments = 5,
7535
- steps = [],
7536
- currentStep = 0,
7537
- showValue = false,
7538
- valuePosition = "right",
7539
- autocolor,
7540
- plusIndicator,
7541
- ...props
7542
- }, ref) => {
7543
- const value = Number(rawValue || 0);
7544
- const indicatorWidth = Math.min(value, 100);
7545
- switch (variant) {
7546
- case "segments":
7547
- return /* @__PURE__ */ jsx41(
7548
- ProgressSegmentsBase,
7549
- {
7550
- label,
7551
- segments,
7552
- value: value || 0
7553
- }
7554
- );
7555
- case "panels":
7556
- return /* @__PURE__ */ jsx41(
7557
- ProgressPanelsBase,
7558
- {
7559
- label,
7560
- steps,
7561
- currentStep
7562
- }
7563
- );
7564
- case "circles":
7565
- return /* @__PURE__ */ jsx41(
7566
- ProgressCirclesBase,
7567
- {
7568
- label,
7569
- steps,
7570
- currentStep
7571
- }
7572
- );
7573
- case "bar":
7574
- default:
7575
- return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1 w-full min-w-[150px]", children: [
7576
- label && /* @__PURE__ */ jsx41(LabelBase_default, { className: "py-2", children: label }),
7577
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
7578
- showValue && valuePosition === "left" && /* @__PURE__ */ jsxs30("div", { className: "w-12 text-sm text-right font-extrabold", children: [
7579
- Math.round(value || 0),
7580
- "%"
7581
- ] }),
7582
- leftIcon && /* @__PURE__ */ jsx41("div", { className: "flex items-center justify-center", children: leftIcon }),
7583
- /* @__PURE__ */ jsxs30(
7584
- ProgressPrimitive.Root,
7585
- {
7586
- ref,
7587
- className: cn(
7588
- " relative h-3 w-full overflow-visible rounded-full bg-muted/80 shadow-inner transition-all ",
7589
- className
7590
- ),
7591
- value,
7592
- ...props,
7593
- children: [
7594
- /* @__PURE__ */ jsx41(
7595
- ProgressPrimitive.Indicator,
7596
- {
7597
- className: cn(
7598
- "h-full transition-all duration-500 ease-in-out rounded-lg",
7599
- // quando não usa autocolor, Indicator deve mostrar a cor primária
7600
- autocolor && autocolor.length >= 2 ? "bg-transparent" : "bg-primary"
7601
- ),
7602
- style: { width: `${indicatorWidth}%` }
7603
- }
7604
- ),
7605
- autocolor && Array.isArray(autocolor) && autocolor.length >= 2 && (() => {
7606
- const [t1Raw, t2Raw] = autocolor;
7607
- const [t1, t2] = [Number(t1Raw), Number(t2Raw)].sort(
7608
- (a, b) => a - b
7609
- );
7610
- const v = Number(value || 0);
7611
- let colorClass = "bg-red-500";
7612
- if (v <= t1) {
7613
- colorClass = "bg-red-500";
7614
- } else if (v <= t2) {
7615
- colorClass = "bg-yellow-500";
7616
- } else {
7617
- colorClass = "bg-emerald-500";
7618
- }
7619
- return /* @__PURE__ */ jsx41(
7620
- "div",
7621
- {
7622
- "aria-hidden": true,
7623
- className: cn(
7624
- "absolute top-0 left-0 h-full transition-all duration-500 ease-in-out rounded-lg",
7625
- colorClass
7626
- ),
7627
- style: { width: `${indicatorWidth}%` }
7628
- }
7629
- );
7630
- })(),
7631
- plusIndicator && value > 100 && /* @__PURE__ */ jsx41(
7632
- "div",
7633
- {
7634
- "aria-hidden": "true",
7635
- className: "absolute top-0 bottom-0 w-0.5 bg-black/70 transition-all duration-500 ease-in-out pointer-events-none",
7636
- style: { left: `100%` },
7637
- children: value > 115 && /* @__PURE__ */ jsx41("div", { className: "absolute left-full ml-2 top-1/2 -translate-y-1/2 text-xs whitespace-nowrap font-extrabold", children: `+${Math.round(
7638
- value - 100
7639
- )}%` })
7640
- }
7641
- ),
7642
- showValue && valuePosition === "inside" && /* @__PURE__ */ jsxs30(
7643
- "span",
7644
- {
7645
- className: "absolute inset-0 flex items-center justify-center text-sm select-none pointer-events-none text-secondary font-extrabold",
7646
- "aria-hidden": true,
7647
- children: [
7648
- Math.round(value || 0),
7649
- "%"
7650
- ]
7651
- }
7652
- )
7653
- ]
7654
- }
7655
- ),
7656
- showValue && valuePosition === "right" && /* @__PURE__ */ jsxs30("div", { className: "w-12 text-sm font-extrabold text-left", children: [
7657
- Math.round(value || 0),
7658
- "%"
7659
- ] }),
7660
- rightIcon && /* @__PURE__ */ jsx41("div", { className: "flex items-center justify-center", children: rightIcon })
7661
- ] })
7662
- ] });
7663
- }
8050
+ variant,
8051
+ size,
8052
+ onClick,
8053
+ disabled,
8054
+ testid,
8055
+ className: cn(
8056
+ "transition-all duration-200 ease-in-out group",
8057
+ "hover:scale-110",
8058
+ "active:scale-95",
8059
+ "disabled:hover:scale-100",
8060
+ !iconColor && (isLiked ? "text-red-500 dark:text-red-400 hover:text-red-600 dark:hover:text-red-300" : "hover:text-red-500 dark:hover:text-red-400"),
8061
+ className
8062
+ ),
8063
+ ...props,
8064
+ children: /* @__PURE__ */ jsx49(
8065
+ HeartIcon,
8066
+ {
8067
+ size: iconSize,
8068
+ color: iconColor,
8069
+ weight: isLiked ? "fill" : "regular",
8070
+ className: "transition-all duration-300 group-hover:scale-110"
8071
+ }
8072
+ )
7664
8073
  }
7665
8074
  );
7666
- ProgressBase.displayName = "ProgressBase";
7667
- var ProgressSegmentsBase = ({
7668
- label,
7669
- segments,
7670
- value
7671
- }) => {
7672
- const filled = Math.round(value / 100 * segments);
7673
- return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1 w-full min-w-[150px]", children: [
7674
- label && /* @__PURE__ */ jsx41(LabelBase_default, { className: "py-2", children: label }),
7675
- /* @__PURE__ */ jsx41("div", { className: "flex gap-1 w-full", children: Array.from({ length: segments }).map((_, idx) => /* @__PURE__ */ jsx41(
7676
- "div",
7677
- {
7678
- className: cn(
7679
- "h-2 flex-1 rounded-full transition-all duration-300",
7680
- idx < filled ? "bg-primary" : "bg-zinc-300 hover:bg-zinc-400"
7681
- )
7682
- },
7683
- idx
7684
- )) })
7685
- ] });
7686
- };
7687
- var ArrowRightIcon = () => /* @__PURE__ */ jsx41(
7688
- "svg",
8075
+ var FavoriteButton = ({
8076
+ disabled,
8077
+ onClick,
8078
+ testid = "button-favorite",
8079
+ isFavorite = false,
8080
+ className,
8081
+ iconSize = 18,
8082
+ iconColor,
8083
+ variant = "ghost",
8084
+ size = "icon",
8085
+ ...props
8086
+ }) => /* @__PURE__ */ jsx49(
8087
+ ButtonBase,
7689
8088
  {
7690
- className: "w-6 h-6 text-zinc-400 transition-transform duration-300 group-hover:translate-x-1",
7691
- fill: "none",
7692
- stroke: "currentColor",
7693
- strokeWidth: 2,
7694
- viewBox: "0 0 24 24",
7695
- xmlns: "http://www.w3.org/2000/svg",
7696
- children: /* @__PURE__ */ jsx41("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" })
8089
+ variant,
8090
+ size,
8091
+ onClick,
8092
+ disabled,
8093
+ testid,
8094
+ className: cn(
8095
+ "transition-all duration-200 ease-in-out group",
8096
+ "hover:scale-110",
8097
+ "active:scale-95",
8098
+ "disabled:hover:scale-100",
8099
+ !iconColor && (isFavorite ? "text-yellow-500 dark:text-yellow-400 hover:text-yellow-600 dark:hover:text-yellow-300" : "hover:text-yellow-500 dark:hover:text-yellow-400"),
8100
+ className
8101
+ ),
8102
+ ...props,
8103
+ children: /* @__PURE__ */ jsx49(
8104
+ StarIcon,
8105
+ {
8106
+ size: iconSize,
8107
+ color: iconColor,
8108
+ weight: isFavorite ? "fill" : "regular",
8109
+ className: "transition-all duration-300 group-hover:rotate-12"
8110
+ }
8111
+ )
7697
8112
  }
7698
8113
  );
7699
- var ProgressPanelsBase = ({
7700
- label,
7701
- steps,
7702
- currentStep
7703
- }) => {
7704
- return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1 w-full", children: [
7705
- label && /* @__PURE__ */ jsx41(LabelBase_default, { className: "py-2", children: label }),
7706
- /* @__PURE__ */ jsx41("div", { className: "flex w-full gap-1 rounded-lg overflow-hidden", children: steps.map((step, idx) => {
7707
- const isActive = idx === currentStep;
7708
- const isLast = idx === steps.length - 1;
7709
- return /* @__PURE__ */ jsxs30(React24.Fragment, { children: [
7710
- /* @__PURE__ */ jsxs30(
7711
- "div",
7712
- {
7713
- className: cn(
7714
- "relative flex items-center justify-center cursor-pointer select-none rounded-lg border transition-shadow duration-300 ease-in-out",
7715
- "hover:shadow-md hover:z-10",
7716
- "aspect-[5/1] min-w-[90px] px-4",
7717
- isActive ? "bg-primary/20 border-2 border-primary shadow-lg font-semibold" : "border-zinc-300"
7718
- ),
7719
- style: { flex: "1 1 0" },
7720
- children: [
7721
- /* @__PURE__ */ jsx41("span", { className: "truncate", children: step }),
7722
- isActive && /* @__PURE__ */ jsx41("div", { className: "absolute bottom-0 left-0 h-1 w-full animate-pulse rounded-b-lg" })
7723
- ]
7724
- }
7725
- ),
7726
- !isLast && /* @__PURE__ */ jsx41("div", { className: "flex items-center px-2 group", children: /* @__PURE__ */ jsx41(ArrowRightIcon, {}) })
7727
- ] }, idx);
7728
- }) })
7729
- ] });
7730
- };
7731
- var ProgressCirclesBase = ({
7732
- label,
7733
- steps,
7734
- currentStep
7735
- }) => {
7736
- return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-2 w-full", children: [
7737
- label && /* @__PURE__ */ jsx41("label", { className: "py-2 text-base font-semibold text-gray-700 dark:text-gray-300", children: label }),
7738
- /* @__PURE__ */ jsxs30("div", { className: "relative flex items-center justify-between w-full", children: [
7739
- /* @__PURE__ */ jsx41("div", { className: "absolute top-5 left-0 w-full h-1 bg-zinc-200 dark:bg-zinc-700" }),
7740
- /* @__PURE__ */ jsx41(
7741
- "div",
7742
- {
7743
- className: "absolute top-5 left-0 h-1 bg-primary transition-all duration-300",
7744
- style: {
7745
- width: `${currentStep / (steps.length - 1) * 100}%`
7746
- }
7747
- }
7748
- ),
7749
- steps.map((step, idx) => {
7750
- const isActive = idx <= currentStep;
7751
- return /* @__PURE__ */ jsxs30(
7752
- "div",
7753
- {
7754
- className: "relative flex flex-col items-center w-10",
7755
- style: { zIndex: isActive ? 10 : 1 },
7756
- children: [
7757
- /* @__PURE__ */ jsx41(
7758
- "div",
7759
- {
7760
- className: cn(
7761
- "w-10 h-10 rounded-full flex items-center justify-center font-bold text-sm transition-all duration-300 cursor-pointer select-none",
7762
- isActive ? "bg-primary text-white dark:text-black shadow-md" : "bg-zinc-200 text-zinc-500 hover:bg-zinc-300 dark:bg-zinc-500 dark:text-black"
7763
- ),
7764
- children: idx + 1
7765
- }
7766
- ),
7767
- /* @__PURE__ */ jsx41("span", { className: "text-xs text-center font-medium mt-1 max-w-[80px] break-words", children: step })
7768
- ]
7769
- },
7770
- idx
7771
- );
7772
- })
7773
- ] })
7774
- ] });
7775
- };
7776
-
7777
- // src/components/ui/feedback/SkeletonBase.tsx
7778
- import { jsx as jsx42 } from "react/jsx-runtime";
7779
- function SkeletonBase({
8114
+ var VisibilityButton = ({
8115
+ disabled,
8116
+ onClick,
8117
+ testid = "button-visibility",
8118
+ isVisible = true,
7780
8119
  className,
8120
+ iconSize = 18,
8121
+ iconColor,
8122
+ variant = "ghost",
8123
+ size = "icon",
7781
8124
  ...props
7782
- }) {
7783
- return /* @__PURE__ */ jsx42("div", { className: cn("animate-pulse bg-primary/10", className), ...props });
7784
- }
7785
-
7786
- // src/components/ui/feedback/SonnerBase.tsx
7787
- import {
7788
- CheckCircleIcon,
7789
- XCircleIcon as XCircleIcon2,
7790
- InfoIcon,
7791
- WarningIcon,
7792
- SpinnerIcon
7793
- } from "@phosphor-icons/react";
7794
- import { Toaster as Sonner, toast as sonnertoast } from "sonner";
7795
- import { jsx as jsx43 } from "react/jsx-runtime";
7796
- var iconBaseClass = "w-5 h-auto";
7797
- var Toaster = ({ testId, ...props }) => {
7798
- return /* @__PURE__ */ jsx43(
7799
- Sonner,
7800
- {
7801
- className: "toaster group",
7802
- position: "top-center",
7803
- toastOptions: {
7804
- classNames: {
7805
- toast: `
7806
- group toast
7807
- bg-background
7808
- text-foreground
7809
- shadow-lg rounded-md
7810
- border-l-4
7811
- border-border
7812
- flex items-center gap-3
7813
- data-[type=success]:border-l-green-500 data-[type=success]:bg-green-50 data-[type=success]:text-green-800 data-[type=success]:border-green-500
7814
- data-[type=error]:border-l-red-500 data-[type=error]:bg-red-50 data-[type=error]:text-red-800 data-[type=error]:border-red-500
7815
- data-[type=WarningIcon]:border-l-yellow-500 data-[type=WarningIcon]:bg-yellow-50 data-[type=WarningIcon]:text-yellow-800 data-[type=WarningIcon]:border-yellow-500
7816
- data-[type=InfoIcon]:border-l-blue-500 data-[type=InfoIcon]:bg-blue-50 data-[type=InfoIcon]:text-blue-800 data-[type=InfoIcon]:border-blue-500
7817
- `,
7818
- description: `
7819
- text-sm
7820
- group-[.toast]:text-neutral-600
7821
- `,
7822
- actionButton: `
7823
- ml-auto
7824
- rounded-md px-3 py-1 text-sm font-semibold
7825
- bg-neutral-800 text-white
7826
- hover:bg-neutral-700
7827
- transition-colors duration-200
7828
- `,
7829
- cancelButton: `
7830
- ml-2
7831
- rounded-md px-3 py-1 text-sm font-semibold
7832
- bg-neutral-100 text-neutral-700
7833
- hover:bg-neutral-200
7834
- transition-colors duration-200
7835
- `
7836
- }
7837
- },
7838
- "data-testid": testId,
7839
- ...props
7840
- }
7841
- );
7842
- };
7843
- var toast2 = {
7844
- success: (message) => sonnertoast.success(message, {
7845
- icon: /* @__PURE__ */ jsx43(CheckCircleIcon, { className: `${iconBaseClass} text-green-600`, weight: "fill" }),
7846
- className: "sonner-success"
7847
- }),
7848
- error: (message) => sonnertoast.error(message, {
7849
- icon: /* @__PURE__ */ jsx43(XCircleIcon2, { className: `${iconBaseClass} text-red-600`, weight: "fill" }),
7850
- className: "sonner-error"
7851
- }),
7852
- warning: (message) => sonnertoast.warning(message, {
7853
- icon: /* @__PURE__ */ jsx43(WarningIcon, { className: `${iconBaseClass} text-yellow-600`, weight: "fill" }),
7854
- className: "sonner-WarningIcon"
7855
- }),
7856
- info: (message) => sonnertoast.info(message, {
7857
- icon: /* @__PURE__ */ jsx43(InfoIcon, { className: `${iconBaseClass} text-blue-600`, weight: "fill" }),
7858
- className: "sonner-InfoIcon"
7859
- }),
7860
- loading: (message) => sonnertoast(message, {
7861
- icon: /* @__PURE__ */ jsx43(SpinnerIcon, { className: `${iconBaseClass} animate-spin text-neutral-500`, weight: "fill" }),
7862
- className: "sonner-loading"
7863
- })
7864
- };
7865
-
7866
- // src/components/ui/form/CheckBoxBase.tsx
7867
- import * as React25 from "react";
7868
- import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
7869
- import { CheckIcon as CheckIcon8 } from "@phosphor-icons/react";
7870
- import { motion as motion11 } from "framer-motion";
7871
- import { jsx as jsx44 } from "react/jsx-runtime";
7872
- var CheckboxBase = React25.forwardRef(({ className, testid: dataTestId = "checkbox-base", ...props }, ref) => /* @__PURE__ */ jsx44(
7873
- CheckboxPrimitive.Root,
8125
+ }) => /* @__PURE__ */ jsx49(
8126
+ ButtonBase,
8127
+ {
8128
+ variant,
8129
+ size,
8130
+ onClick,
8131
+ disabled,
8132
+ testid,
8133
+ className: cn(
8134
+ "transition-all duration-200 ease-in-out",
8135
+ "hover:scale-105",
8136
+ "active:scale-95",
8137
+ "disabled:hover:scale-100",
8138
+ className
8139
+ ),
8140
+ ...props,
8141
+ children: isVisible ? /* @__PURE__ */ jsx49(
8142
+ EyeIcon,
8143
+ {
8144
+ size: iconSize,
8145
+ color: iconColor,
8146
+ className: "transition-opacity duration-200"
8147
+ }
8148
+ ) : /* @__PURE__ */ jsx49(
8149
+ EyeSlashIcon,
8150
+ {
8151
+ size: iconSize,
8152
+ color: iconColor,
8153
+ className: "transition-opacity duration-200"
8154
+ }
8155
+ )
8156
+ }
8157
+ );
8158
+ var ViewButton = (props) => /* @__PURE__ */ jsx49(VisibilityButton, { isVisible: true, testid: "button-view", ...props });
8159
+ var HideButton = (props) => /* @__PURE__ */ jsx49(VisibilityButton, { isVisible: false, testid: "button-hide", ...props });
8160
+ var LockButton = ({
8161
+ disabled,
8162
+ onClick,
8163
+ testid = "button-lock",
8164
+ isLocked = true,
8165
+ className,
8166
+ iconSize = 18,
8167
+ iconColor,
8168
+ variant = "ghost",
8169
+ size = "icon",
8170
+ ...props
8171
+ }) => /* @__PURE__ */ jsx49(
8172
+ ButtonBase,
7874
8173
  {
7875
- ref,
8174
+ variant,
8175
+ size,
8176
+ onClick,
8177
+ disabled,
8178
+ testid,
7876
8179
  className: cn(
7877
- "peer h-4 w-4 shrink-0 rounded-md border border-primary shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground transition-colors",
8180
+ "transition-all duration-200 ease-in-out group",
8181
+ "hover:scale-105",
8182
+ "active:scale-95",
8183
+ "disabled:hover:scale-100",
8184
+ !iconColor && (isLocked ? "text-red-500 dark:text-red-400 hover:text-red-600 dark:hover:text-red-300" : "text-emerald-500 dark:text-emerald-400 hover:text-emerald-600 dark:hover:text-emerald-300"),
7878
8185
  className
7879
8186
  ),
7880
- "data-testid": dataTestId,
7881
8187
  ...props,
7882
- children: /* @__PURE__ */ jsx44(CheckboxPrimitive.Indicator, { asChild: true, children: /* @__PURE__ */ jsx44(
7883
- motion11.div,
8188
+ children: isLocked ? /* @__PURE__ */ jsx49(
8189
+ LockIcon,
7884
8190
  {
7885
- initial: { scale: 0, opacity: 0, rotate: -90 },
7886
- animate: { scale: 1, opacity: 1, rotate: 0 },
7887
- exit: { scale: 0, opacity: 0, rotate: 90 },
7888
- transition: { type: "spring", stiffness: 500, damping: 30 },
7889
- className: "flex items-center justify-center text-current",
7890
- children: /* @__PURE__ */ jsx44(CheckIcon8, { className: "h-4 w-4", weight: "bold" })
8191
+ size: iconSize,
8192
+ color: iconColor,
8193
+ className: "transition-all duration-200 group-hover:scale-110"
7891
8194
  }
7892
- ) })
7893
- }
7894
- ));
7895
- CheckboxBase.displayName = CheckboxPrimitive.Root.displayName;
7896
-
7897
- // src/components/ui/form/CollapsibleBase.tsx
7898
- import * as React26 from "react";
7899
- import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
7900
- import { CaretUpDownIcon } from "@phosphor-icons/react";
7901
- import { jsx as jsx45, jsxs as jsxs31 } from "react/jsx-runtime";
7902
- var CollapsibleBase = React26.forwardRef(({ ...props }, ref) => {
7903
- return /* @__PURE__ */ jsx45(CollapsiblePrimitive.Root, { ref, "data-slot": "collapsible", ...props });
7904
- });
7905
- CollapsibleBase.displayName = CollapsiblePrimitive.Root.displayName;
7906
- var CollapsibleTriggerBase = React26.forwardRef(({ className, children, leftIcon, showCaret = true, ...props }, ref) => {
7907
- return /* @__PURE__ */ jsxs31(
7908
- CollapsiblePrimitive.CollapsibleTrigger,
7909
- {
7910
- ref,
7911
- className: cn(
7912
- "flex w-full items-center justify-between p-3 text-left font-medium transition-all duration-500 ease-[cubic-bezier(0.4,0,0.2,1)] hover:bg-accent hover:text-accent-foreground rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 [&[data-state=open]_.caret-icon]:rotate-180",
7913
- className
7914
- ),
7915
- "data-slot": "collapsible-trigger",
7916
- ...props,
7917
- children: [
7918
- /* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-2", children: [
7919
- leftIcon && /* @__PURE__ */ jsx45("span", { className: "flex-shrink-0 [&>svg]:size-4", children: leftIcon }),
7920
- /* @__PURE__ */ jsx45("span", { children })
7921
- ] }),
7922
- showCaret && /* @__PURE__ */ jsx45("span", { className: "caret-icon flex-shrink-0 transition-transform duration-500 ease-[cubic-bezier(0.4,0,0.2,1)]", children: /* @__PURE__ */ jsx45(CaretUpDownIcon, { className: "h-4 w-4" }) })
7923
- ]
7924
- }
7925
- );
7926
- });
7927
- CollapsibleTriggerBase.displayName = CollapsiblePrimitive.CollapsibleTrigger.displayName;
7928
- var CollapsibleContentBase = React26.forwardRef(({ className, children, ...props }, ref) => {
7929
- return /* @__PURE__ */ jsx45(
7930
- CollapsiblePrimitive.CollapsibleContent,
7931
- {
7932
- ref,
7933
- className: cn(
7934
- "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
7935
- className
7936
- ),
7937
- "data-slot": "collapsible-content",
7938
- ...props,
7939
- children: /* @__PURE__ */ jsx45("div", { className: "pb-3 pt-1", children })
7940
- }
7941
- );
7942
- });
7943
- CollapsibleContentBase.displayName = CollapsiblePrimitive.CollapsibleContent.displayName;
7944
-
7945
- // src/components/ui/form/DebounceInput.tsx
7946
- import { useEffect as useEffect10, useState as useState11 } from "react";
7947
- import { CircleNotchIcon } from "@phosphor-icons/react";
7948
- import { jsx as jsx46 } from "react/jsx-runtime";
7949
-
7950
- // src/components/ui/form/HoverCardBase.tsx
7951
- import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
7952
- import { jsx as jsx47 } from "react/jsx-runtime";
7953
- function HoverCardBase(props) {
7954
- return /* @__PURE__ */ jsx47(HoverCardPrimitive.Root, { ...props });
7955
- }
7956
- function HoverCardTriggerBase(props) {
7957
- return /* @__PURE__ */ jsx47(HoverCardPrimitive.Trigger, { ...props });
7958
- }
7959
- function HoverCardContentBase({
7960
- className,
7961
- align = "center",
7962
- sideOffset = 4,
7963
- ...props
7964
- }) {
7965
- return /* @__PURE__ */ jsx47(HoverCardPrimitive.Portal, { children: /* @__PURE__ */ jsx47(
7966
- HoverCardPrimitive.Content,
7967
- {
7968
- align,
7969
- sideOffset,
7970
- className: cn(
7971
- "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
7972
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
7973
- "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0",
7974
- "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95",
7975
- "data-[side=bottom]:slide-in-from-top-2",
7976
- "data-[side=left]:slide-in-from-right-2",
7977
- "data-[side=right]:slide-in-from-left-2",
7978
- "data-[side=top]:slide-in-from-bottom-2",
7979
- className
7980
- ),
7981
- ...props
7982
- }
7983
- ) });
7984
- }
7985
-
7986
- // src/components/ui/form/Input-OTP-Base.tsx
7987
- import * as React27 from "react";
7988
- import { OTPInput, OTPInputContext } from "input-otp";
7989
- import { MinusIcon } from "@phosphor-icons/react";
7990
- import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
7991
- function InputOTPBase({
7992
- className,
7993
- containerClassName,
7994
- ...props
7995
- }) {
7996
- return /* @__PURE__ */ jsx48(
7997
- OTPInput,
7998
- {
7999
- "data-slot": "input-otp",
8000
- containerClassName: cn(
8001
- "flex items-center gap-2 has-disabled:opacity-50",
8002
- containerClassName
8003
- ),
8004
- className: cn("disabled:cursor-not-allowed", className),
8005
- ...props
8006
- }
8007
- );
8008
- }
8009
- function InputOTPGroupBase({ className, ...props }) {
8010
- return /* @__PURE__ */ jsx48(
8011
- "div",
8012
- {
8013
- "data-slot": "input-otp-group",
8014
- className: cn("flex items-center", className),
8015
- ...props
8016
- }
8017
- );
8018
- }
8019
- function InputOTPSlotBase({
8020
- index,
8021
- className,
8022
- ...props
8023
- }) {
8024
- const inputOTPContext = React27.useContext(OTPInputContext);
8025
- const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
8026
- return /* @__PURE__ */ jsxs32(
8027
- "div",
8028
- {
8029
- "data-slot": "input-otp-slot",
8030
- "data-active": isActive,
8031
- className: cn(
8032
- "data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-9 w-9 items-center justify-center border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]",
8033
- className
8034
- ),
8035
- ...props,
8036
- children: [
8037
- char,
8038
- hasFakeCaret && /* @__PURE__ */ jsx48("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx48("div", { className: "animate-caret-blink bg-foreground h-4 w-px duration-1000" }) })
8039
- ]
8040
- }
8041
- );
8042
- }
8043
- function InputOTPSeparatorBase({ ...props }) {
8044
- return /* @__PURE__ */ jsx48("div", { "data-slot": "input-otp-separator", role: "separator", ...props, children: /* @__PURE__ */ jsx48(MinusIcon, {}) });
8045
- }
8046
-
8047
- // src/components/ui/form/SliderBase.tsx
8048
- import * as React28 from "react";
8049
- import * as SliderPrimitive from "@radix-ui/react-slider";
8050
- import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
8051
- var SlideBase = React28.forwardRef(
8052
- ({
8053
- className,
8054
- orientation = "horizontal",
8055
- label,
8056
- leftIcon,
8057
- rightIcon,
8058
- ...props
8059
- }, ref) => {
8060
- const isVertical = orientation === "vertical";
8061
- return /* @__PURE__ */ jsxs33(
8062
- "div",
8195
+ ) : /* @__PURE__ */ jsx49(
8196
+ LockOpenIcon,
8063
8197
  {
8064
- className: cn("flex flex-col gap-1", isVertical ? "h-full " : "w-full"),
8065
- children: [
8066
- label && /* @__PURE__ */ jsx49(LabelBase_default, { className: "py-2", children: label }),
8067
- /* @__PURE__ */ jsxs33(
8068
- "div",
8069
- {
8070
- className: cn(
8071
- "flex gap-2",
8072
- isVertical ? "flex-col h-full" : "flex-row items-center w-full"
8073
- ),
8074
- children: [
8075
- leftIcon && /* @__PURE__ */ jsx49("div", { className: "flex items-center justify-center", children: leftIcon }),
8076
- /* @__PURE__ */ jsxs33(
8077
- SliderPrimitive.Root,
8078
- {
8079
- ref,
8080
- orientation,
8081
- className: cn(
8082
- "relative flex touch-none select-none items-center",
8083
- isVertical ? "flex-col h-full" : "flex-row w-full",
8084
- className
8085
- ),
8086
- ...props,
8087
- children: [
8088
- /* @__PURE__ */ jsx49(
8089
- SliderPrimitive.Track,
8090
- {
8091
- className: cn(
8092
- "relative overflow-hidden bg-primary/20 rounded-full",
8093
- isVertical ? "w-1.5 h-full" : "h-1.5 w-full"
8094
- ),
8095
- children: /* @__PURE__ */ jsx49(
8096
- SliderPrimitive.Range,
8097
- {
8098
- className: cn(
8099
- "absolute bg-primary",
8100
- isVertical ? "w-full" : "h-full"
8101
- )
8102
- }
8103
- )
8104
- }
8105
- ),
8106
- /* @__PURE__ */ jsx49(
8107
- SliderPrimitive.Thumb,
8108
- {
8109
- className: cn(
8110
- "block h-4 w-4 rounded-full border border-primary/70 bg-background shadow-md transition-transform",
8111
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2",
8112
- "hover:scale-125 active:scale-125"
8113
- )
8114
- }
8115
- )
8116
- ]
8117
- }
8118
- ),
8119
- rightIcon && /* @__PURE__ */ jsx49("div", { className: "flex items-center justify-center", children: rightIcon })
8120
- ]
8121
- }
8122
- )
8123
- ]
8198
+ size: iconSize,
8199
+ color: iconColor,
8200
+ className: "transition-all duration-200 group-hover:scale-110"
8124
8201
  }
8125
- );
8202
+ )
8126
8203
  }
8127
8204
  );
8128
- SlideBase.displayName = "SlideBase";
8205
+ var UnlockButton = (props) => /* @__PURE__ */ jsx49(LockButton, { isLocked: false, testid: "button-unlock", ...props });
8129
8206
 
8130
8207
  // src/components/ui/form/SwitchBase.tsx
8131
8208
  import * as React29 from "react";
@@ -8162,7 +8239,7 @@ SwitchBase.displayName = SwitchPrimitives.Root.displayName;
8162
8239
  // src/components/ui/form/TextAreaBase.tsx
8163
8240
  import * as React30 from "react";
8164
8241
  import { motion as motion12 } from "framer-motion";
8165
- import { TrashIcon as TrashIcon3 } from "@phosphor-icons/react";
8242
+ import { TrashIcon as TrashIcon2 } from "@phosphor-icons/react";
8166
8243
  import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
8167
8244
  var TextAreaBase = React30.forwardRef(
8168
8245
  ({ className, clearable = false, onClear, ...props }, ref) => {
@@ -8259,7 +8336,7 @@ var TextAreaBase = React30.forwardRef(
8259
8336
  ),
8260
8337
  disabled: props.disabled,
8261
8338
  "aria-label": "Limpar texto",
8262
- children: /* @__PURE__ */ jsx51(TrashIcon3, { size: 16, weight: "regular" })
8339
+ children: /* @__PURE__ */ jsx51(TrashIcon2, { size: 16, weight: "regular" })
8263
8340
  }
8264
8341
  ) }),
8265
8342
  /* @__PURE__ */ jsxs34(
@@ -10512,7 +10589,8 @@ function DateTimePicker({
10512
10589
  label,
10513
10590
  date,
10514
10591
  onChange,
10515
- display,
10592
+ displayFormat,
10593
+ hideTime,
10516
10594
  hideSeconds,
10517
10595
  hideHour,
10518
10596
  hideMinute,
@@ -10543,12 +10621,16 @@ function DateTimePicker({
10543
10621
  onChange(newDate);
10544
10622
  };
10545
10623
  const getTimeFormat = () => {
10624
+ if (hideTime) return "";
10546
10625
  if (hideHour && hideMinute) return "";
10547
10626
  if (hideHour) return hideSeconds ? "mm" : "mm:ss";
10548
10627
  if (hideMinute) return hideSeconds ? "HH" : "HH':00'";
10549
10628
  return hideSeconds ? "HH:mm" : "HH:mm:ss";
10550
10629
  };
10551
10630
  const getDisplayFormat = () => {
10631
+ if (displayFormat) {
10632
+ return displayFormat;
10633
+ }
10552
10634
  const timeFormat = getTimeFormat();
10553
10635
  if (!timeFormat) return "PPP";
10554
10636
  return `PPP - ${timeFormat}`;
@@ -10570,7 +10652,7 @@ function DateTimePicker({
10570
10652
  !date && "text-muted-foreground/"
10571
10653
  ),
10572
10654
  children: [
10573
- /* @__PURE__ */ jsx66("span", { className: "truncate flex-1", children: date ? display ? format(date, "dd/MM/yyyy") : format(date, getDisplayFormat(), { locale: ptBR }) : "Selecione uma Data" }),
10655
+ /* @__PURE__ */ jsx66("span", { className: "truncate flex-1", children: date ? format(date, getDisplayFormat(), { locale: ptBR }) : "Selecione uma data" }),
10574
10656
  /* @__PURE__ */ jsx66(CalendarBlankIcon, { className: "flex-shrink-0 w-5 h-5 sm:w-6 sm:h-6" })
10575
10657
  ]
10576
10658
  }
@@ -10596,10 +10678,13 @@ function DateTimePicker({
10596
10678
  initialFocus: true,
10597
10679
  fromDate,
10598
10680
  toDate,
10599
- className: cn("w-full", hideHour && hideMinute && "border-0")
10681
+ className: cn(
10682
+ "w-full",
10683
+ (hideTime || hideHour && hideMinute) && "border-0"
10684
+ )
10600
10685
  }
10601
10686
  ),
10602
- !(hideHour && hideMinute) && /* @__PURE__ */ jsx66("div", { className: "flex justify-center w-full px-2", children: /* @__PURE__ */ jsxs45(
10687
+ !hideTime && !(hideHour && hideMinute) && /* @__PURE__ */ jsx66("div", { className: "flex justify-center w-full px-2", children: /* @__PURE__ */ jsxs45(
10603
10688
  PopoverBase,
10604
10689
  {
10605
10690
  open: timePickerOpen,
@@ -10847,7 +10932,7 @@ function RangePicker({
10847
10932
  whileHover: { scale: 1.03 },
10848
10933
  whileTap: { scale: 0.95 },
10849
10934
  children: /* @__PURE__ */ jsx67(
10850
- DeleteButton,
10935
+ ButtonBase,
10851
10936
  {
10852
10937
  variant: "outline",
10853
10938
  onClick: handleClear,
@@ -11248,7 +11333,6 @@ export {
11248
11333
  ContextMenuTriggerBase,
11249
11334
  CopyButton,
11250
11335
  DateTimePicker,
11251
- DeleteButton,
11252
11336
  DestructiveDialog,
11253
11337
  DialogBase,
11254
11338
  DialogCloseBase,