@iclips/ui 1.0.2 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as AccordionPrimitive from '@radix-ui/react-accordion';
2
- import { MoreVertical, AlertCircle, Calendar, CheckSquare, MessageSquare, Paperclip, ChevronDownIcon, Home, Folder, Users, BarChart3, Settings, Pin, Plus, LayoutGrid, FileText, Star, Download, Sparkles, ChevronRight, Zap, PanelLeftClose, PanelLeft, Bell, MoreHorizontal, Printer, Eye, ChevronLeft, ArrowLeft, ArrowRight, Check, CheckIcon, CircleIcon, ChevronRightIcon, XIcon, SearchIcon, MinusIcon, ChevronLeftIcon, MoreHorizontalIcon, GripVerticalIcon, ChevronUpIcon, PanelLeftIcon } from 'lucide-react';
2
+ import { MoreVertical, AlertCircle, Calendar, CheckSquare, MessageSquare, Paperclip, ChevronDownIcon, Home, Folder, Users, BarChart3, Settings, Pin, Plus, LayoutGrid, FileText, Star, Download, Sparkles, ChevronRight, Zap, PanelLeftClose, PanelLeft, Bell, MoreHorizontal, ChevronLeft, Printer, Eye, ArrowLeft, ArrowRight, Check, CheckIcon, ChevronUpIcon, Clock, CalendarIcon, CircleIcon, ChevronRightIcon, XIcon, SearchIcon, MinusIcon, ChevronLeftIcon, MoreHorizontalIcon, GripVerticalIcon, PanelLeftIcon, ChevronsLeft, ChevronsRight, X, Filter, Search, ArrowUpDown, Trash2 } from 'lucide-react';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import * as React7 from 'react';
7
- import { useState } from 'react';
7
+ import { useState, useMemo } from 'react';
8
8
  import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
9
9
  import { Slot } from '@radix-ui/react-slot';
10
10
  import { cva } from 'class-variance-authority';
@@ -12,6 +12,7 @@ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
12
12
  import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio';
13
13
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
14
14
  import { DayPicker } from 'react-day-picker';
15
+ import { ptBR } from 'date-fns/locale';
15
16
  import useEmblaCarousel from 'embla-carousel-react';
16
17
  import * as RechartsPrimitive from 'recharts';
17
18
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
@@ -19,8 +20,8 @@ import { HexColorPicker } from 'react-colorful';
19
20
  import * as PopoverPrimitive from '@radix-ui/react-popover';
20
21
  import * as LabelPrimitive from '@radix-ui/react-label';
21
22
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
22
- import { format } from 'date-fns';
23
- import * as SeparatorPrimitive from '@radix-ui/react-separator';
23
+ import { format, subDays, startOfMonth, endOfMonth, subMonths } from 'date-fns';
24
+ import * as SelectPrimitive from '@radix-ui/react-select';
24
25
  import * as ProgressPrimitive from '@radix-ui/react-progress';
25
26
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
26
27
  import { Command as Command$1 } from 'cmdk';
@@ -34,7 +35,7 @@ import * as MenubarPrimitive from '@radix-ui/react-menubar';
34
35
  import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
35
36
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
36
37
  import * as ResizablePrimitive from 'react-resizable-panels';
37
- import * as SelectPrimitive from '@radix-ui/react-select';
38
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
38
39
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
39
40
  import * as SliderPrimitive from '@radix-ui/react-slider';
40
41
  import { useTheme } from 'next-themes';
@@ -816,6 +817,62 @@ function BreadcrumbEllipsis({
816
817
  }
817
818
  );
818
819
  }
820
+ function Calendar2({
821
+ className,
822
+ classNames,
823
+ showOutsideDays = true,
824
+ locale = ptBR,
825
+ ...props
826
+ }) {
827
+ return /* @__PURE__ */ jsx(
828
+ DayPicker,
829
+ {
830
+ showOutsideDays,
831
+ locale,
832
+ className: cn("p-3", className),
833
+ classNames: {
834
+ months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
835
+ month: "space-y-4",
836
+ month_caption: "flex justify-center pt-1 relative items-center",
837
+ caption_label: "text-sm font-medium",
838
+ nav: "space-x-1 flex items-center",
839
+ button_previous: cn(
840
+ buttonVariants({ variant: "outline" }),
841
+ "absolute left-1 top-0 size-7 bg-background p-0 hover:bg-accent hover:text-accent-foreground rounded-md border-border m-5 z-10"
842
+ ),
843
+ button_next: cn(
844
+ buttonVariants({ variant: "outline" }),
845
+ "absolute right-1 top-0 size-7 bg-background p-0 hover:bg-accent hover:text-accent-foreground rounded-md border-border m-5 z-10"
846
+ ),
847
+ month_grid: "w-full border-collapse space-y-1",
848
+ weekdays: "flex",
849
+ weekday: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
850
+ week: "flex w-full mt-2",
851
+ day: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20 rounded-md",
852
+ day_button: cn(
853
+ buttonVariants({ variant: "ghost" }),
854
+ "h-9 w-9 p-0 font-normal aria-selected:opacity-100 rounded-md"
855
+ ),
856
+ range_end: "day-range-end",
857
+ selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground rounded-md",
858
+ today: "bg-accent text-accent-foreground rounded-md",
859
+ outside: "day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
860
+ disabled: "text-muted-foreground opacity-50",
861
+ range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
862
+ hidden: "invisible",
863
+ ...classNames
864
+ },
865
+ components: {
866
+ Chevron: ({ orientation }) => {
867
+ const Icon2 = orientation === "left" ? ChevronLeft : ChevronRight;
868
+ return /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4" });
869
+ }
870
+ },
871
+ ...props
872
+ }
873
+ );
874
+ }
875
+ Calendar2.displayName = "Calendar";
819
876
  function Card({ className, ...props }) {
820
877
  return /* @__PURE__ */ jsx(
821
878
  "div",
@@ -1694,59 +1751,6 @@ var ContractPrintPreview = React7.forwardRef(({ data, logo, showServices = true,
1694
1751
  ) });
1695
1752
  });
1696
1753
  ContractPrintPreview.displayName = "ContractPrintPreview";
1697
- function Calendar2({
1698
- className,
1699
- classNames,
1700
- showOutsideDays = true,
1701
- ...props
1702
- }) {
1703
- return /* @__PURE__ */ jsx(
1704
- DayPicker,
1705
- {
1706
- showOutsideDays,
1707
- className: cn("p-3", className),
1708
- classNames: {
1709
- months: "flex flex-col sm:flex-row gap-2",
1710
- month: "flex flex-col gap-4",
1711
- caption: "flex justify-center pt-1 relative items-center w-full",
1712
- caption_label: "text-sm font-medium",
1713
- nav: "flex items-center gap-1",
1714
- nav_button: cn(
1715
- "size-7 bg-transparent p-0 opacity-50 hover:opacity-100"
1716
- ),
1717
- nav_button_previous: "absolute left-1",
1718
- nav_button_next: "absolute right-1",
1719
- table: "w-full border-collapse space-x-1",
1720
- head_row: "flex",
1721
- head_cell: "text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]",
1722
- row: "flex w-full mt-2",
1723
- cell: cn(
1724
- "relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-range-end)]:rounded-r-md",
1725
- props.mode === "range" ? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" : "[&:has([aria-selected])]:rounded-md"
1726
- ),
1727
- day: cn(
1728
- "size-8 p-0 font-normal aria-selected:opacity-100"
1729
- ),
1730
- day_range_start: "day-range-start aria-selected:bg-primary aria-selected:text-primary-foreground",
1731
- day_range_end: "day-range-end aria-selected:bg-primary aria-selected:text-primary-foreground",
1732
- day_selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
1733
- day_today: "bg-accent text-accent-foreground",
1734
- day_outside: "day-outside text-muted-foreground aria-selected:text-muted-foreground",
1735
- day_disabled: "text-muted-foreground opacity-50",
1736
- day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
1737
- day_hidden: "invisible",
1738
- ...classNames
1739
- },
1740
- components: {
1741
- Chevron: ({ orientation, ...props2 }) => {
1742
- const Icon2 = orientation === "left" ? ChevronLeft : ChevronRight;
1743
- return /* @__PURE__ */ jsx(Icon2, { className: "size-4", ...props2 });
1744
- }
1745
- },
1746
- ...props
1747
- }
1748
- );
1749
- }
1750
1754
  var CarouselContext = React7.createContext(null);
1751
1755
  function useCarousel() {
1752
1756
  const context = React7.useContext(CarouselContext);
@@ -2420,362 +2424,725 @@ function CollapsibleContent2({
2420
2424
  }
2421
2425
  );
2422
2426
  }
2423
- function TimePicker({
2424
- date,
2425
- onChange,
2426
- label,
2427
+ function Select({
2428
+ ...props
2429
+ }) {
2430
+ return /* @__PURE__ */ jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
2431
+ }
2432
+ function SelectGroup({
2433
+ ...props
2434
+ }) {
2435
+ return /* @__PURE__ */ jsx(SelectPrimitive.Group, { "data-slot": "select-group", ...props });
2436
+ }
2437
+ function SelectValue({
2438
+ ...props
2439
+ }) {
2440
+ return /* @__PURE__ */ jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
2441
+ }
2442
+ function SelectTrigger({
2427
2443
  className,
2428
- disabled = false
2444
+ size = "default",
2445
+ children,
2446
+ ...props
2429
2447
  }) {
2430
- const [hours, setHours] = React7.useState(
2431
- date ? String(date.getHours()).padStart(2, "0") : "00"
2432
- );
2433
- const [minutes, setMinutes] = React7.useState(
2434
- date ? String(date.getMinutes()).padStart(2, "0") : "00"
2435
- );
2436
- React7.useEffect(() => {
2437
- if (date) {
2438
- setHours(String(date.getHours()).padStart(2, "0"));
2439
- setMinutes(String(date.getMinutes()).padStart(2, "0"));
2440
- }
2441
- }, [date]);
2442
- const handleHoursChange = (e) => {
2443
- let value = e.target.value.replace(/\D/g, "");
2444
- if (value.length > 2) {
2445
- value = value.slice(0, 2);
2446
- }
2447
- const numValue = parseInt(value) || 0;
2448
- if (numValue > 23) {
2449
- value = "23";
2450
- }
2451
- setHours(value);
2452
- if (value.length === 2) {
2453
- updateDateTime(parseInt(value), parseInt(minutes));
2454
- }
2455
- };
2456
- const handleMinutesChange = (e) => {
2457
- let value = e.target.value.replace(/\D/g, "");
2458
- if (value.length > 2) {
2459
- value = value.slice(0, 2);
2460
- }
2461
- const numValue = parseInt(value) || 0;
2462
- if (numValue > 59) {
2463
- value = "59";
2464
- }
2465
- setMinutes(value);
2466
- if (value.length === 2) {
2467
- updateDateTime(parseInt(hours), parseInt(value));
2468
- }
2469
- };
2470
- const handleHoursBlur = () => {
2471
- const paddedHours = hours.padStart(2, "0");
2472
- setHours(paddedHours);
2473
- updateDateTime(parseInt(paddedHours), parseInt(minutes));
2474
- };
2475
- const handleMinutesBlur = () => {
2476
- const paddedMinutes = minutes.padStart(2, "0");
2477
- setMinutes(paddedMinutes);
2478
- updateDateTime(parseInt(hours), parseInt(paddedMinutes));
2479
- };
2480
- const updateDateTime = (h, m) => {
2481
- const newDate = date ? new Date(date) : /* @__PURE__ */ new Date();
2482
- newDate.setHours(h);
2483
- newDate.setMinutes(m);
2484
- newDate.setSeconds(0);
2485
- newDate.setMilliseconds(0);
2486
- onChange?.(newDate);
2487
- };
2488
- return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
2489
- label && /* @__PURE__ */ jsx(Label, { children: label }),
2490
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2491
- /* @__PURE__ */ jsx(
2492
- Input,
2493
- {
2494
- type: "text",
2495
- value: hours,
2496
- onChange: handleHoursChange,
2497
- onBlur: handleHoursBlur,
2498
- placeholder: "00",
2499
- className: "w-16 text-center font-mono",
2500
- maxLength: 2,
2501
- disabled,
2502
- "aria-label": "Horas"
2503
- }
2448
+ return /* @__PURE__ */ jsxs(
2449
+ SelectPrimitive.Trigger,
2450
+ {
2451
+ "data-slot": "select-trigger",
2452
+ "data-size": size,
2453
+ className: cn(
2454
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-full items-center justify-between gap-2 rounded-md border bg-input-background px-3 py-2 text-sm whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
2455
+ className
2504
2456
  ),
2505
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground font-medium", children: ":" }),
2506
- /* @__PURE__ */ jsx(
2507
- Input,
2508
- {
2509
- type: "text",
2510
- value: minutes,
2511
- onChange: handleMinutesChange,
2512
- onBlur: handleMinutesBlur,
2513
- placeholder: "00",
2514
- className: "w-16 text-center font-mono",
2515
- maxLength: 2,
2516
- disabled,
2517
- "aria-label": "Minutos"
2518
- }
2519
- )
2520
- ] })
2521
- ] });
2457
+ ...props,
2458
+ children: [
2459
+ children,
2460
+ /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" }) })
2461
+ ]
2462
+ }
2463
+ );
2522
2464
  }
2523
- function DateTimePicker({
2524
- date,
2525
- onChange,
2526
- label,
2527
- placeholder = "Selecione data e hora",
2465
+ function SelectContent({
2528
2466
  className,
2529
- disabled = false
2467
+ children,
2468
+ position = "popper",
2469
+ ...props
2530
2470
  }) {
2531
- const [open, setOpen] = React7.useState(false);
2532
- const [selectedDate, setSelectedDate] = React7.useState(date);
2533
- React7.useEffect(() => {
2534
- setSelectedDate(date);
2535
- }, [date]);
2536
- const handleDateSelect = (newDate) => {
2537
- if (newDate) {
2538
- const updated = new Date(newDate);
2539
- if (selectedDate) {
2540
- updated.setHours(selectedDate.getHours());
2541
- updated.setMinutes(selectedDate.getMinutes());
2542
- }
2543
- setSelectedDate(updated);
2544
- } else {
2545
- setSelectedDate(void 0);
2546
- }
2547
- };
2548
- const handleTimeChange = (newDate) => {
2549
- setSelectedDate(newDate);
2550
- };
2551
- const handleConfirm = () => {
2552
- onChange?.(selectedDate);
2553
- setOpen(false);
2554
- };
2555
- const handleCancel = () => {
2556
- setSelectedDate(date);
2557
- setOpen(false);
2558
- };
2559
- return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
2560
- label && /* @__PURE__ */ jsx(Label, { children: label }),
2561
- /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
2562
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2563
- Button,
2564
- {
2565
- variant: "outline",
2566
- className: cn(
2567
- "w-full justify-start text-left font-normal",
2568
- !selectedDate && "text-muted-foreground"
2569
- ),
2570
- disabled,
2571
- children: [
2572
- /* @__PURE__ */ jsx(Calendar, { className: "mr-2 h-4 w-4" }),
2573
- selectedDate ? format(selectedDate, "dd/MM/yyyy HH:mm") : /* @__PURE__ */ jsx("span", { children: placeholder })
2574
- ]
2575
- }
2576
- ) }),
2577
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "p-3 space-y-3", children: [
2471
+ return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
2472
+ SelectPrimitive.Content,
2473
+ {
2474
+ "data-slot": "select-content",
2475
+ className: cn(
2476
+ "bg-popover text-popover-foreground 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
2477
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
2478
+ className
2479
+ ),
2480
+ position,
2481
+ ...props,
2482
+ children: [
2483
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
2578
2484
  /* @__PURE__ */ jsx(
2579
- Calendar2,
2485
+ SelectPrimitive.Viewport,
2580
2486
  {
2581
- mode: "single",
2582
- selected: selectedDate,
2583
- onSelect: handleDateSelect,
2584
- initialFocus: true
2487
+ className: cn(
2488
+ "p-1",
2489
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
2490
+ ),
2491
+ children
2585
2492
  }
2586
2493
  ),
2587
- /* @__PURE__ */ jsx("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsx(
2588
- TimePicker,
2589
- {
2590
- date: selectedDate,
2591
- onChange: handleTimeChange,
2592
- label: "Hor\xE1rio"
2593
- }
2594
- ) }),
2595
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2 pt-2", children: [
2596
- /* @__PURE__ */ jsx(
2597
- Button,
2598
- {
2599
- variant: "outline",
2600
- size: "sm",
2601
- onClick: handleCancel,
2602
- className: "flex-1",
2603
- children: "Cancelar"
2604
- }
2605
- ),
2606
- /* @__PURE__ */ jsx(
2607
- Button,
2608
- {
2609
- size: "sm",
2610
- onClick: handleConfirm,
2611
- className: "flex-1",
2612
- children: "Confirmar"
2613
- }
2614
- )
2615
- ] })
2616
- ] }) })
2617
- ] })
2618
- ] });
2494
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
2495
+ ]
2496
+ }
2497
+ ) });
2619
2498
  }
2620
- function Separator({
2499
+ function SelectLabel({
2621
2500
  className,
2622
- orientation = "horizontal",
2623
- decorative = true,
2624
2501
  ...props
2625
2502
  }) {
2626
2503
  return /* @__PURE__ */ jsx(
2627
- SeparatorPrimitive.Root,
2504
+ SelectPrimitive.Label,
2628
2505
  {
2629
- "data-slot": "separator-root",
2630
- decorative,
2631
- orientation,
2506
+ "data-slot": "select-label",
2507
+ className: cn("text-muted-foreground px-2 py-1.5 text-xs", className),
2508
+ ...props
2509
+ }
2510
+ );
2511
+ }
2512
+ function SelectItem({
2513
+ className,
2514
+ children,
2515
+ ...props
2516
+ }) {
2517
+ return /* @__PURE__ */ jsxs(
2518
+ SelectPrimitive.Item,
2519
+ {
2520
+ "data-slot": "select-item",
2632
2521
  className: cn(
2633
- "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
2522
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
2634
2523
  className
2635
2524
  ),
2636
- ...props
2525
+ ...props,
2526
+ children: [
2527
+ /* @__PURE__ */ jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
2528
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
2529
+ ]
2637
2530
  }
2638
2531
  );
2639
2532
  }
2640
- function DateRangePicker({
2641
- dateRange,
2642
- onChange,
2643
- label,
2644
- placeholder = "Selecione o per\xEDodo",
2533
+ function SelectSeparator({
2645
2534
  className,
2646
- disabled = false,
2647
- withTime = false
2535
+ ...props
2648
2536
  }) {
2649
- const [open, setOpen] = React7.useState(false);
2650
- const [range, setRange] = React7.useState(dateRange);
2651
- React7.useEffect(() => {
2652
- setRange(dateRange);
2653
- }, [dateRange]);
2654
- const handleRangeSelect = (newRange) => {
2655
- if (newRange?.from && range?.from) {
2656
- const updatedFrom = new Date(newRange.from);
2657
- updatedFrom.setHours(range.from.getHours());
2658
- updatedFrom.setMinutes(range.from.getMinutes());
2659
- let updatedTo = newRange.to ? new Date(newRange.to) : void 0;
2660
- if (updatedTo && range?.to) {
2661
- updatedTo.setHours(range.to.getHours());
2662
- updatedTo.setMinutes(range.to.getMinutes());
2663
- }
2664
- setRange({ from: updatedFrom, to: updatedTo });
2665
- } else {
2666
- setRange(newRange);
2667
- }
2668
- };
2669
- const handleStartTimeChange = (newDate) => {
2670
- if (newDate && range?.from) {
2671
- setRange({
2672
- ...range,
2673
- from: newDate
2674
- });
2675
- }
2676
- };
2677
- const handleEndTimeChange = (newDate) => {
2678
- if (newDate && range?.to) {
2679
- setRange({
2680
- ...range,
2681
- to: newDate
2682
- });
2537
+ return /* @__PURE__ */ jsx(
2538
+ SelectPrimitive.Separator,
2539
+ {
2540
+ "data-slot": "select-separator",
2541
+ className: cn("bg-border pointer-events-none -mx-1 my-1 h-px", className),
2542
+ ...props
2683
2543
  }
2684
- };
2685
- const handleConfirm = () => {
2686
- onChange?.(range);
2687
- setOpen(false);
2688
- };
2689
- const handleCancel = () => {
2690
- setRange(dateRange);
2691
- setOpen(false);
2692
- };
2693
- const formatRangeDisplay = () => {
2694
- if (!range?.from) {
2695
- return placeholder;
2544
+ );
2545
+ }
2546
+ function SelectScrollUpButton({
2547
+ className,
2548
+ ...props
2549
+ }) {
2550
+ return /* @__PURE__ */ jsx(
2551
+ SelectPrimitive.ScrollUpButton,
2552
+ {
2553
+ "data-slot": "select-scroll-up-button",
2554
+ className: cn(
2555
+ "flex cursor-default items-center justify-center py-1",
2556
+ className
2557
+ ),
2558
+ ...props,
2559
+ children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "size-4" })
2560
+ }
2561
+ );
2562
+ }
2563
+ function SelectScrollDownButton({
2564
+ className,
2565
+ ...props
2566
+ }) {
2567
+ return /* @__PURE__ */ jsx(
2568
+ SelectPrimitive.ScrollDownButton,
2569
+ {
2570
+ "data-slot": "select-scroll-down-button",
2571
+ className: cn(
2572
+ "flex cursor-default items-center justify-center py-1",
2573
+ className
2574
+ ),
2575
+ ...props,
2576
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })
2577
+ }
2578
+ );
2579
+ }
2580
+ var generateHours = (format3) => {
2581
+ const hours = [];
2582
+ const max = format3 === "24h" ? 24 : 12;
2583
+ const start = format3 === "24h" ? 0 : 1;
2584
+ for (let i = start; i < max + start; i++) {
2585
+ hours.push(i.toString().padStart(2, "0"));
2586
+ }
2587
+ return hours;
2588
+ };
2589
+ var generateMinutes = (step) => {
2590
+ const minutes = [];
2591
+ for (let i = 0; i < 60; i += step) {
2592
+ minutes.push(i.toString().padStart(2, "0"));
2593
+ }
2594
+ return minutes;
2595
+ };
2596
+ var to12HourFormat = (hour) => {
2597
+ const period = hour >= 12 ? "PM" : "AM";
2598
+ const hour12 = hour % 12 || 12;
2599
+ return { hour: hour12, period };
2600
+ };
2601
+ var to24HourFormat = (hour, period) => {
2602
+ if (period === "AM") {
2603
+ return hour === 12 ? 0 : hour;
2604
+ }
2605
+ return hour === 12 ? 12 : hour + 12;
2606
+ };
2607
+ var isTimeInRange = (time, minTime, maxTime) => {
2608
+ if (!minTime && !maxTime) return true;
2609
+ const [h, m] = time.split(":").map(Number);
2610
+ const timeMinutes = h * 60 + m;
2611
+ if (minTime) {
2612
+ const [minH, minM] = minTime.split(":").map(Number);
2613
+ if (timeMinutes < minH * 60 + minM) return false;
2614
+ }
2615
+ if (maxTime) {
2616
+ const [maxH, maxM] = maxTime.split(":").map(Number);
2617
+ if (timeMinutes > maxH * 60 + maxM) return false;
2618
+ }
2619
+ return true;
2620
+ };
2621
+ function TimePicker({
2622
+ value,
2623
+ onChange,
2624
+ format: format3 = "24h",
2625
+ minuteStep = 5,
2626
+ minTime,
2627
+ maxTime,
2628
+ disabled = false,
2629
+ placeholder = "HH:MM",
2630
+ className,
2631
+ showIcon = true,
2632
+ variant = "input"
2633
+ }) {
2634
+ const [hour, minute] = React7.useMemo(() => {
2635
+ if (!value) return ["", ""];
2636
+ const [h, m] = value.split(":");
2637
+ return [h || "", m || ""];
2638
+ }, [value]);
2639
+ const [period, setPeriod] = React7.useState(() => {
2640
+ if (!hour) return "AM";
2641
+ return parseInt(hour) >= 12 ? "PM" : "AM";
2642
+ });
2643
+ const updateTime = (newHour, newMinute, newPeriod) => {
2644
+ if (!newHour || !newMinute) return;
2645
+ let h = parseInt(newHour);
2646
+ const m = parseInt(newMinute);
2647
+ if (format3 === "12h" && newPeriod) {
2648
+ h = to24HourFormat(h, newPeriod);
2696
2649
  }
2697
- const fromFormat = withTime ? "dd/MM/yyyy HH:mm" : "dd/MM/yyyy";
2698
- const toFormat = withTime ? "dd/MM/yyyy HH:mm" : "dd/MM/yyyy";
2699
- if (range.to) {
2700
- return `${format(range.from, fromFormat)} - ${format(range.to, toFormat)}`;
2650
+ const timeStr = `${h.toString().padStart(2, "0")}:${m.toString().padStart(2, "0")}`;
2651
+ if (isTimeInRange(timeStr, minTime, maxTime)) {
2652
+ onChange?.(timeStr);
2701
2653
  }
2702
- return format(range.from, fromFormat);
2703
2654
  };
2704
- return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
2705
- label && /* @__PURE__ */ jsx(Label, { children: label }),
2706
- /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
2707
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2708
- Button,
2655
+ const handleInputChange = (e) => {
2656
+ const inputValue = e.target.value;
2657
+ const cleaned = inputValue.replace(/[^\d:]/g, "");
2658
+ if (cleaned.length === 2 && !cleaned.includes(":")) {
2659
+ const formatted = cleaned + ":";
2660
+ onChange?.(formatted);
2661
+ return;
2662
+ }
2663
+ if (cleaned.match(/^\d{2}:\d{2}$/)) {
2664
+ const [h, m] = cleaned.split(":").map(Number);
2665
+ if (h >= 0 && h <= 23 && m >= 0 && m <= 59) {
2666
+ if (isTimeInRange(cleaned, minTime, maxTime)) {
2667
+ onChange?.(cleaned);
2668
+ }
2669
+ }
2670
+ } else {
2671
+ onChange?.(cleaned);
2672
+ }
2673
+ };
2674
+ if (variant === "input") {
2675
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
2676
+ showIcon && /* @__PURE__ */ jsx(Clock, { className: "absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground pointer-events-none" }),
2677
+ /* @__PURE__ */ jsx(
2678
+ Input,
2709
2679
  {
2710
- variant: "outline",
2711
- className: cn(
2712
- "w-full justify-start text-left font-normal",
2713
- !range && "text-muted-foreground"
2714
- ),
2680
+ type: "text",
2681
+ value: value || "",
2682
+ onChange: handleInputChange,
2683
+ placeholder,
2684
+ disabled,
2685
+ className: cn(showIcon && "pl-9"),
2686
+ maxLength: 5
2687
+ }
2688
+ )
2689
+ ] });
2690
+ }
2691
+ if (variant === "select") {
2692
+ const hours = generateHours(format3);
2693
+ const minutes = generateMinutes(minuteStep);
2694
+ const displayHour = format3 === "12h" && hour ? to12HourFormat(parseInt(hour)).hour.toString().padStart(2, "0") : hour;
2695
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
2696
+ showIcon && /* @__PURE__ */ jsx(Clock, { className: "size-4 text-muted-foreground" }),
2697
+ /* @__PURE__ */ jsxs(
2698
+ Select,
2699
+ {
2700
+ value: displayHour,
2701
+ onValueChange: (h) => {
2702
+ const effectivePeriod = format3 === "12h" ? period : void 0;
2703
+ updateTime(h, minute || "00", effectivePeriod);
2704
+ },
2705
+ disabled,
2706
+ children: [
2707
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[70px]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "HH" }) }),
2708
+ /* @__PURE__ */ jsx(SelectContent, { children: hours.map((h) => /* @__PURE__ */ jsx(SelectItem, { value: h, children: h }, h)) })
2709
+ ]
2710
+ }
2711
+ ),
2712
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground font-medium", children: ":" }),
2713
+ /* @__PURE__ */ jsxs(
2714
+ Select,
2715
+ {
2716
+ value: minute,
2717
+ onValueChange: (m) => {
2718
+ const effectivePeriod = format3 === "12h" ? period : void 0;
2719
+ updateTime(hour || "00", m, effectivePeriod);
2720
+ },
2721
+ disabled,
2722
+ children: [
2723
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[70px]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "MM" }) }),
2724
+ /* @__PURE__ */ jsx(SelectContent, { children: minutes.map((m) => /* @__PURE__ */ jsx(SelectItem, { value: m, children: m }, m)) })
2725
+ ]
2726
+ }
2727
+ ),
2728
+ format3 === "12h" && /* @__PURE__ */ jsxs(
2729
+ Select,
2730
+ {
2731
+ value: period,
2732
+ onValueChange: (p) => {
2733
+ setPeriod(p);
2734
+ if (hour && minute) {
2735
+ updateTime(hour, minute, p);
2736
+ }
2737
+ },
2738
+ disabled,
2739
+ children: [
2740
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[70px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
2741
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
2742
+ /* @__PURE__ */ jsx(SelectItem, { value: "AM", children: "AM" }),
2743
+ /* @__PURE__ */ jsx(SelectItem, { value: "PM", children: "PM" })
2744
+ ] })
2745
+ ]
2746
+ }
2747
+ )
2748
+ ] });
2749
+ }
2750
+ if (variant === "inline") {
2751
+ const hours = generateHours(format3);
2752
+ const minutes = generateMinutes(minuteStep);
2753
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
2754
+ showIcon && /* @__PURE__ */ jsx(Clock, { className: "size-4 text-muted-foreground" }),
2755
+ /* @__PURE__ */ jsx(Label, { className: "text-sm text-muted-foreground", children: "Hor\xE1rio:" }),
2756
+ /* @__PURE__ */ jsxs(
2757
+ Select,
2758
+ {
2759
+ value: hour,
2760
+ onValueChange: (h) => updateTime(h, minute || "00", format3 === "12h" ? period : void 0),
2761
+ disabled,
2762
+ children: [
2763
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[65px] h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "HH" }) }),
2764
+ /* @__PURE__ */ jsx(SelectContent, { children: hours.map((h) => /* @__PURE__ */ jsx(SelectItem, { value: h, children: h }, h)) })
2765
+ ]
2766
+ }
2767
+ ),
2768
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: ":" }),
2769
+ /* @__PURE__ */ jsxs(
2770
+ Select,
2771
+ {
2772
+ value: minute,
2773
+ onValueChange: (m) => updateTime(hour || "00", m, format3 === "12h" ? period : void 0),
2774
+ disabled,
2775
+ children: [
2776
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[65px] h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "MM" }) }),
2777
+ /* @__PURE__ */ jsx(SelectContent, { children: minutes.map((m) => /* @__PURE__ */ jsx(SelectItem, { value: m, children: m }, m)) })
2778
+ ]
2779
+ }
2780
+ ),
2781
+ format3 === "12h" && /* @__PURE__ */ jsxs(
2782
+ Select,
2783
+ {
2784
+ value: period,
2785
+ onValueChange: (p) => {
2786
+ setPeriod(p);
2787
+ if (hour && minute) {
2788
+ updateTime(hour, minute, p);
2789
+ }
2790
+ },
2715
2791
  disabled,
2716
2792
  children: [
2717
- /* @__PURE__ */ jsx(Calendar, { className: "mr-2 h-4 w-4" }),
2718
- /* @__PURE__ */ jsx("span", { children: formatRangeDisplay() })
2793
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[65px] h-8 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
2794
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
2795
+ /* @__PURE__ */ jsx(SelectItem, { value: "AM", children: "AM" }),
2796
+ /* @__PURE__ */ jsx(SelectItem, { value: "PM", children: "PM" })
2797
+ ] })
2719
2798
  ]
2720
2799
  }
2800
+ )
2801
+ ] });
2802
+ }
2803
+ return null;
2804
+ }
2805
+ TimePicker.displayName = "TimePicker";
2806
+ function DatePicker({
2807
+ value,
2808
+ onChange,
2809
+ placeholder = "Selecione uma data",
2810
+ disabled = false,
2811
+ minDate,
2812
+ maxDate,
2813
+ dateFormat,
2814
+ locale = ptBR,
2815
+ className,
2816
+ error = false,
2817
+ showTime = false,
2818
+ timeFormat = "24h",
2819
+ minuteStep = 5,
2820
+ defaultTime = "09:00",
2821
+ id,
2822
+ name
2823
+ }) {
2824
+ const [open, setOpen] = React7.useState(false);
2825
+ const displayFormat = dateFormat || (showTime ? "dd/MM/yyyy HH:mm" : "dd/MM/yyyy");
2826
+ const currentTime = React7.useMemo(() => {
2827
+ if (!value) return defaultTime;
2828
+ const hours = value.getHours().toString().padStart(2, "0");
2829
+ const minutes = value.getMinutes().toString().padStart(2, "0");
2830
+ return `${hours}:${minutes}`;
2831
+ }, [value, defaultTime]);
2832
+ const handleDateSelect = (date) => {
2833
+ if (!date) {
2834
+ onChange?.(void 0);
2835
+ return;
2836
+ }
2837
+ if (showTime) {
2838
+ const [hours, minutes] = currentTime.split(":").map(Number);
2839
+ date.setHours(hours, minutes, 0, 0);
2840
+ } else {
2841
+ date.setHours(0, 0, 0, 0);
2842
+ }
2843
+ onChange?.(date);
2844
+ if (!showTime) {
2845
+ setOpen(false);
2846
+ }
2847
+ };
2848
+ const handleTimeChange = (time) => {
2849
+ if (!value) {
2850
+ const today = /* @__PURE__ */ new Date();
2851
+ const [hours, minutes] = time.split(":").map(Number);
2852
+ today.setHours(hours, minutes, 0, 0);
2853
+ onChange?.(today);
2854
+ } else {
2855
+ const newDate = new Date(value);
2856
+ const [hours, minutes] = time.split(":").map(Number);
2857
+ newDate.setHours(hours, minutes, 0, 0);
2858
+ onChange?.(newDate);
2859
+ }
2860
+ };
2861
+ const displayValue = React7.useMemo(() => {
2862
+ if (!value) return "";
2863
+ return format(value, displayFormat, { locale });
2864
+ }, [value, displayFormat, locale]);
2865
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
2866
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2867
+ Button,
2868
+ {
2869
+ id,
2870
+ name,
2871
+ variant: "outline",
2872
+ disabled,
2873
+ className: cn(
2874
+ "w-full justify-start text-left font-normal",
2875
+ !value && "text-muted-foreground",
2876
+ error && "border-destructive focus-visible:ring-destructive/20",
2877
+ className
2878
+ ),
2879
+ children: [
2880
+ /* @__PURE__ */ jsx(CalendarIcon, { className: "mr-2 size-4" }),
2881
+ displayValue || placeholder
2882
+ ]
2883
+ }
2884
+ ) }),
2885
+ /* @__PURE__ */ jsxs(PopoverContent, { className: "w-auto p-0", align: "start", children: [
2886
+ /* @__PURE__ */ jsx(
2887
+ Calendar2,
2888
+ {
2889
+ mode: "single",
2890
+ selected: value,
2891
+ onSelect: handleDateSelect,
2892
+ disabled: (date) => {
2893
+ if (minDate && date < minDate) return true;
2894
+ if (maxDate && date > maxDate) return true;
2895
+ return false;
2896
+ },
2897
+ locale,
2898
+ initialFocus: true
2899
+ }
2900
+ ),
2901
+ showTime && /* @__PURE__ */ jsx("div", { className: "border-t p-3", children: /* @__PURE__ */ jsx(
2902
+ TimePicker,
2903
+ {
2904
+ value: currentTime,
2905
+ onChange: handleTimeChange,
2906
+ format: timeFormat,
2907
+ minuteStep,
2908
+ variant: "inline",
2909
+ showIcon: true
2910
+ }
2721
2911
  ) }),
2722
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "p-3 space-y-3", children: [
2912
+ showTime && /* @__PURE__ */ jsx("div", { className: "border-t p-3 flex justify-end", children: /* @__PURE__ */ jsx(
2913
+ Button,
2914
+ {
2915
+ size: "sm",
2916
+ onClick: () => setOpen(false),
2917
+ children: "Confirmar"
2918
+ }
2919
+ ) })
2920
+ ] })
2921
+ ] });
2922
+ }
2923
+ DatePicker.displayName = "DatePicker";
2924
+ var getDefaultPresets = () => {
2925
+ const today = /* @__PURE__ */ new Date();
2926
+ today.setHours(0, 0, 0, 0);
2927
+ return [
2928
+ {
2929
+ label: "Hoje",
2930
+ value: { from: today, to: today }
2931
+ },
2932
+ {
2933
+ label: "\xDAltimos 7 dias",
2934
+ value: { from: subDays(today, 6), to: today }
2935
+ },
2936
+ {
2937
+ label: "\xDAltimos 30 dias",
2938
+ value: { from: subDays(today, 29), to: today }
2939
+ },
2940
+ {
2941
+ label: "Este m\xEAs",
2942
+ value: { from: startOfMonth(today), to: today }
2943
+ },
2944
+ {
2945
+ label: "M\xEAs passado",
2946
+ value: {
2947
+ from: startOfMonth(subMonths(today, 1)),
2948
+ to: endOfMonth(subMonths(today, 1))
2949
+ }
2950
+ }
2951
+ ];
2952
+ };
2953
+ function DateRangePicker({
2954
+ value,
2955
+ onChange,
2956
+ placeholder = "Selecione um per\xEDodo",
2957
+ disabled = false,
2958
+ minDate,
2959
+ maxDate,
2960
+ dateFormat = "dd/MM/yyyy",
2961
+ locale = ptBR,
2962
+ className,
2963
+ error = false,
2964
+ numberOfMonths = 2,
2965
+ showTime = false,
2966
+ timeFormat = "24h",
2967
+ minuteStep = 15,
2968
+ presets,
2969
+ showDefaultPresets = true,
2970
+ id,
2971
+ name
2972
+ }) {
2973
+ const [open, setOpen] = React7.useState(false);
2974
+ const displayFormat = showTime ? `${dateFormat} HH:mm` : dateFormat;
2975
+ const allPresets = React7.useMemo(() => {
2976
+ const defaults = showDefaultPresets ? getDefaultPresets() : [];
2977
+ return [...defaults, ...presets || []];
2978
+ }, [presets, showDefaultPresets]);
2979
+ const startTime = React7.useMemo(() => {
2980
+ if (!value?.from) return "00:00";
2981
+ const h = value.from.getHours().toString().padStart(2, "0");
2982
+ const m = value.from.getMinutes().toString().padStart(2, "0");
2983
+ return `${h}:${m}`;
2984
+ }, [value?.from]);
2985
+ const endTime = React7.useMemo(() => {
2986
+ if (!value?.to) return "23:59";
2987
+ const h = value.to.getHours().toString().padStart(2, "0");
2988
+ const m = value.to.getMinutes().toString().padStart(2, "0");
2989
+ return `${h}:${m}`;
2990
+ }, [value?.to]);
2991
+ const handleDateSelect = (range) => {
2992
+ if (!range) {
2993
+ onChange?.(void 0);
2994
+ return;
2995
+ }
2996
+ if (showTime) {
2997
+ if (range.from) {
2998
+ const [h, m] = startTime.split(":").map(Number);
2999
+ range.from.setHours(h, m, 0, 0);
3000
+ }
3001
+ if (range.to) {
3002
+ const [h, m] = endTime.split(":").map(Number);
3003
+ range.to.setHours(h, m, 0, 0);
3004
+ }
3005
+ } else {
3006
+ if (range.from) range.from.setHours(0, 0, 0, 0);
3007
+ if (range.to) range.to.setHours(23, 59, 59, 999);
3008
+ }
3009
+ onChange?.(range);
3010
+ };
3011
+ const handleStartTimeChange = (time) => {
3012
+ if (!value?.from) return;
3013
+ const newFrom = new Date(value.from);
3014
+ const [h, m] = time.split(":").map(Number);
3015
+ newFrom.setHours(h, m, 0, 0);
3016
+ onChange?.({ ...value, from: newFrom });
3017
+ };
3018
+ const handleEndTimeChange = (time) => {
3019
+ if (!value?.to) return;
3020
+ const newTo = new Date(value.to);
3021
+ const [h, m] = time.split(":").map(Number);
3022
+ newTo.setHours(h, m, 0, 0);
3023
+ onChange?.({ ...value, to: newTo });
3024
+ };
3025
+ const handlePresetSelect = (preset) => {
3026
+ const newRange = {
3027
+ from: new Date(preset.value.from),
3028
+ to: new Date(preset.value.to)
3029
+ };
3030
+ if (showTime) {
3031
+ const [sh, sm] = startTime.split(":").map(Number);
3032
+ const [eh, em] = endTime.split(":").map(Number);
3033
+ newRange.from.setHours(sh, sm, 0, 0);
3034
+ newRange.to.setHours(eh, em, 0, 0);
3035
+ }
3036
+ onChange?.(newRange);
3037
+ };
3038
+ const displayValue = React7.useMemo(() => {
3039
+ if (!value?.from) return "";
3040
+ const fromStr = format(value.from, displayFormat, { locale });
3041
+ if (!value.to) return fromStr;
3042
+ const toStr = format(value.to, displayFormat, { locale });
3043
+ return `${fromStr} \u2192 ${toStr}`;
3044
+ }, [value, displayFormat, locale]);
3045
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
3046
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
3047
+ Button,
3048
+ {
3049
+ id,
3050
+ name,
3051
+ variant: "outline",
3052
+ disabled,
3053
+ className: cn(
3054
+ "w-full justify-start text-left font-normal",
3055
+ !value && "text-muted-foreground",
3056
+ error && "border-destructive focus-visible:ring-destructive/20",
3057
+ className
3058
+ ),
3059
+ children: [
3060
+ /* @__PURE__ */ jsx(CalendarIcon, { className: "mr-2 size-4" }),
3061
+ displayValue || placeholder
3062
+ ]
3063
+ }
3064
+ ) }),
3065
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "flex", children: [
3066
+ allPresets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "border-r p-3 space-y-1 min-w-[140px]", children: [
3067
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Atalhos" }),
3068
+ allPresets.map((preset) => /* @__PURE__ */ jsx(
3069
+ Button,
3070
+ {
3071
+ variant: "ghost",
3072
+ size: "sm",
3073
+ className: "w-full justify-start text-sm h-8",
3074
+ onClick: () => handlePresetSelect(preset),
3075
+ children: preset.label
3076
+ },
3077
+ preset.label
3078
+ ))
3079
+ ] }),
3080
+ /* @__PURE__ */ jsxs("div", { children: [
2723
3081
  /* @__PURE__ */ jsx(
2724
3082
  Calendar2,
2725
3083
  {
2726
3084
  mode: "range",
2727
- selected: range,
2728
- onSelect: handleRangeSelect,
2729
- numberOfMonths: 2,
3085
+ selected: value,
3086
+ onSelect: handleDateSelect,
3087
+ numberOfMonths,
3088
+ disabled: (date) => {
3089
+ if (minDate && date < minDate) return true;
3090
+ if (maxDate && date > maxDate) return true;
3091
+ return false;
3092
+ },
3093
+ locale,
2730
3094
  initialFocus: true
2731
3095
  }
2732
3096
  ),
2733
- withTime && range?.from && /* @__PURE__ */ jsxs(Fragment, { children: [
2734
- /* @__PURE__ */ jsx(Separator, {}),
2735
- /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
3097
+ showTime && value?.from && value?.to && /* @__PURE__ */ jsxs("div", { className: "border-t p-3 flex gap-6", children: [
3098
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
3099
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Hora in\xEDcio" }),
2736
3100
  /* @__PURE__ */ jsx(
2737
3101
  TimePicker,
2738
3102
  {
2739
- date: range.from,
3103
+ value: startTime,
2740
3104
  onChange: handleStartTimeChange,
2741
- label: "Hora de In\xEDcio"
3105
+ format: timeFormat,
3106
+ minuteStep,
3107
+ variant: "select",
3108
+ showIcon: false
2742
3109
  }
2743
- ),
2744
- range.to && /* @__PURE__ */ jsx(
3110
+ )
3111
+ ] }),
3112
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
3113
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: "Hora fim" }),
3114
+ /* @__PURE__ */ jsx(
2745
3115
  TimePicker,
2746
3116
  {
2747
- date: range.to,
3117
+ value: endTime,
2748
3118
  onChange: handleEndTimeChange,
2749
- label: "Hora de T\xE9rmino"
3119
+ format: timeFormat,
3120
+ minuteStep,
3121
+ variant: "select",
3122
+ showIcon: false
2750
3123
  }
2751
3124
  )
2752
3125
  ] })
2753
3126
  ] }),
2754
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2 pt-2", children: [
3127
+ /* @__PURE__ */ jsxs("div", { className: "border-t p-3 flex justify-end gap-2", children: [
2755
3128
  /* @__PURE__ */ jsx(
2756
3129
  Button,
2757
3130
  {
2758
3131
  variant: "outline",
2759
3132
  size: "sm",
2760
- onClick: handleCancel,
2761
- className: "flex-1",
2762
- children: "Cancelar"
3133
+ onClick: () => {
3134
+ onChange?.(void 0);
3135
+ },
3136
+ children: "Limpar"
2763
3137
  }
2764
3138
  ),
2765
- /* @__PURE__ */ jsx(
2766
- Button,
2767
- {
2768
- size: "sm",
2769
- onClick: handleConfirm,
2770
- className: "flex-1",
2771
- children: "Confirmar"
2772
- }
2773
- )
3139
+ /* @__PURE__ */ jsx(Button, { size: "sm", onClick: () => setOpen(false), children: "Confirmar" })
2774
3140
  ] })
2775
- ] }) })
2776
- ] })
3141
+ ] })
3142
+ ] }) })
2777
3143
  ] });
2778
3144
  }
3145
+ DateRangePicker.displayName = "DateRangePicker";
2779
3146
  function Progress({
2780
3147
  className,
2781
3148
  value,
@@ -4568,183 +4935,50 @@ function ResizableHandle({
4568
4935
  }
4569
4936
  );
4570
4937
  }
4571
- function Select({
4938
+ function Separator5({
4939
+ className,
4940
+ orientation = "horizontal",
4941
+ decorative = true,
4572
4942
  ...props
4573
4943
  }) {
4574
- return /* @__PURE__ */ jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
4944
+ return /* @__PURE__ */ jsx(
4945
+ SeparatorPrimitive.Root,
4946
+ {
4947
+ "data-slot": "separator-root",
4948
+ decorative,
4949
+ orientation,
4950
+ className: cn(
4951
+ "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
4952
+ className
4953
+ ),
4954
+ ...props
4955
+ }
4956
+ );
4575
4957
  }
4576
- function SelectGroup({
4958
+ function Sheet({ ...props }) {
4959
+ return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "sheet", ...props });
4960
+ }
4961
+ function SheetTrigger({
4577
4962
  ...props
4578
4963
  }) {
4579
- return /* @__PURE__ */ jsx(SelectPrimitive.Group, { "data-slot": "select-group", ...props });
4964
+ return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
4580
4965
  }
4581
- function SelectValue({
4966
+ function SheetClose({
4582
4967
  ...props
4583
4968
  }) {
4584
- return /* @__PURE__ */ jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
4969
+ return /* @__PURE__ */ jsx(DialogPrimitive.Close, { "data-slot": "sheet-close", ...props });
4585
4970
  }
4586
- function SelectTrigger({
4587
- className,
4588
- size = "default",
4589
- children,
4971
+ function SheetPortal({
4590
4972
  ...props
4591
4973
  }) {
4592
- return /* @__PURE__ */ jsxs(
4593
- SelectPrimitive.Trigger,
4974
+ return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
4975
+ }
4976
+ var SheetOverlay = React7.forwardRef(({ className, ...props }, ref) => {
4977
+ return /* @__PURE__ */ jsx(
4978
+ DialogPrimitive.Overlay,
4594
4979
  {
4595
- "data-slot": "select-trigger",
4596
- "data-size": size,
4597
- className: cn(
4598
- "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-full items-center justify-between gap-2 rounded-md border bg-input-background px-3 py-2 text-sm whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
4599
- className
4600
- ),
4601
- ...props,
4602
- children: [
4603
- children,
4604
- /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" }) })
4605
- ]
4606
- }
4607
- );
4608
- }
4609
- function SelectContent({
4610
- className,
4611
- children,
4612
- position = "popper",
4613
- ...props
4614
- }) {
4615
- return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
4616
- SelectPrimitive.Content,
4617
- {
4618
- "data-slot": "select-content",
4619
- className: cn(
4620
- "bg-popover text-popover-foreground 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
4621
- position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
4622
- className
4623
- ),
4624
- position,
4625
- ...props,
4626
- children: [
4627
- /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
4628
- /* @__PURE__ */ jsx(
4629
- SelectPrimitive.Viewport,
4630
- {
4631
- className: cn(
4632
- "p-1",
4633
- position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
4634
- ),
4635
- children
4636
- }
4637
- ),
4638
- /* @__PURE__ */ jsx(SelectScrollDownButton, {})
4639
- ]
4640
- }
4641
- ) });
4642
- }
4643
- function SelectLabel({
4644
- className,
4645
- ...props
4646
- }) {
4647
- return /* @__PURE__ */ jsx(
4648
- SelectPrimitive.Label,
4649
- {
4650
- "data-slot": "select-label",
4651
- className: cn("text-muted-foreground px-2 py-1.5 text-xs", className),
4652
- ...props
4653
- }
4654
- );
4655
- }
4656
- function SelectItem({
4657
- className,
4658
- children,
4659
- ...props
4660
- }) {
4661
- return /* @__PURE__ */ jsxs(
4662
- SelectPrimitive.Item,
4663
- {
4664
- "data-slot": "select-item",
4665
- className: cn(
4666
- "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
4667
- className
4668
- ),
4669
- ...props,
4670
- children: [
4671
- /* @__PURE__ */ jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
4672
- /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
4673
- ]
4674
- }
4675
- );
4676
- }
4677
- function SelectSeparator({
4678
- className,
4679
- ...props
4680
- }) {
4681
- return /* @__PURE__ */ jsx(
4682
- SelectPrimitive.Separator,
4683
- {
4684
- "data-slot": "select-separator",
4685
- className: cn("bg-border pointer-events-none -mx-1 my-1 h-px", className),
4686
- ...props
4687
- }
4688
- );
4689
- }
4690
- function SelectScrollUpButton({
4691
- className,
4692
- ...props
4693
- }) {
4694
- return /* @__PURE__ */ jsx(
4695
- SelectPrimitive.ScrollUpButton,
4696
- {
4697
- "data-slot": "select-scroll-up-button",
4698
- className: cn(
4699
- "flex cursor-default items-center justify-center py-1",
4700
- className
4701
- ),
4702
- ...props,
4703
- children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "size-4" })
4704
- }
4705
- );
4706
- }
4707
- function SelectScrollDownButton({
4708
- className,
4709
- ...props
4710
- }) {
4711
- return /* @__PURE__ */ jsx(
4712
- SelectPrimitive.ScrollDownButton,
4713
- {
4714
- "data-slot": "select-scroll-down-button",
4715
- className: cn(
4716
- "flex cursor-default items-center justify-center py-1",
4717
- className
4718
- ),
4719
- ...props,
4720
- children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })
4721
- }
4722
- );
4723
- }
4724
- function Sheet({ ...props }) {
4725
- return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "sheet", ...props });
4726
- }
4727
- function SheetTrigger({
4728
- ...props
4729
- }) {
4730
- return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
4731
- }
4732
- function SheetClose({
4733
- ...props
4734
- }) {
4735
- return /* @__PURE__ */ jsx(DialogPrimitive.Close, { "data-slot": "sheet-close", ...props });
4736
- }
4737
- function SheetPortal({
4738
- ...props
4739
- }) {
4740
- return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
4741
- }
4742
- var SheetOverlay = React7.forwardRef(({ className, ...props }, ref) => {
4743
- return /* @__PURE__ */ jsx(
4744
- DialogPrimitive.Overlay,
4745
- {
4746
- ref,
4747
- "data-slot": "sheet-overlay",
4980
+ ref,
4981
+ "data-slot": "sheet-overlay",
4748
4982
  className: cn(
4749
4983
  "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
4750
4984
  className
@@ -5176,7 +5410,7 @@ function SidebarSeparator({
5176
5410
  ...props
5177
5411
  }) {
5178
5412
  return /* @__PURE__ */ jsx(
5179
- Separator,
5413
+ Separator5,
5180
5414
  {
5181
5415
  "data-slot": "sidebar-separator",
5182
5416
  "data-sidebar": "separator",
@@ -5590,56 +5824,72 @@ function Switch({
5590
5824
  }
5591
5825
  );
5592
5826
  }
5593
- function Table({ className, ...props }) {
5594
- return /* @__PURE__ */ jsx(
5595
- "div",
5596
- {
5597
- "data-slot": "table-container",
5598
- className: "relative w-full overflow-x-auto",
5599
- children: /* @__PURE__ */ jsx(
5600
- "table",
5601
- {
5602
- "data-slot": "table",
5603
- className: cn("w-full caption-bottom text-sm", className),
5604
- ...props
5605
- }
5606
- )
5607
- }
5608
- );
5609
- }
5610
- function TableHeader({ className, ...props }) {
5611
- return /* @__PURE__ */ jsx(
5612
- "thead",
5613
- {
5614
- "data-slot": "table-header",
5615
- className: cn("[&_tr]:border-b", className),
5616
- ...props
5617
- }
5618
- );
5619
- }
5620
- function TableBody({ className, ...props }) {
5621
- return /* @__PURE__ */ jsx(
5622
- "tbody",
5623
- {
5624
- "data-slot": "table-body",
5625
- className: cn("[&_tr:last-child]:border-0", className),
5626
- ...props
5627
- }
5628
- );
5629
- }
5630
- function TableFooter({ className, ...props }) {
5631
- return /* @__PURE__ */ jsx(
5632
- "tfoot",
5633
- {
5634
- "data-slot": "table-footer",
5635
- className: cn(
5636
- "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
5637
- className
5638
- ),
5639
- ...props
5640
- }
5641
- );
5642
- }
5827
+ var Table = React7.forwardRef(
5828
+ ({ className, ...props }, ref) => {
5829
+ return /* @__PURE__ */ jsx(
5830
+ "div",
5831
+ {
5832
+ "data-slot": "table-container",
5833
+ className: "relative w-full overflow-x-auto",
5834
+ children: /* @__PURE__ */ jsx(
5835
+ "table",
5836
+ {
5837
+ ref,
5838
+ "data-slot": "table",
5839
+ className: cn("w-full caption-bottom text-sm", className),
5840
+ ...props
5841
+ }
5842
+ )
5843
+ }
5844
+ );
5845
+ }
5846
+ );
5847
+ Table.displayName = "Table";
5848
+ var TableHeader = React7.forwardRef(
5849
+ ({ className, ...props }, ref) => {
5850
+ return /* @__PURE__ */ jsx(
5851
+ "thead",
5852
+ {
5853
+ ref,
5854
+ "data-slot": "table-header",
5855
+ className: cn("[&_tr]:border-b", className),
5856
+ ...props
5857
+ }
5858
+ );
5859
+ }
5860
+ );
5861
+ TableHeader.displayName = "TableHeader";
5862
+ var TableBody = React7.forwardRef(
5863
+ ({ className, ...props }, ref) => {
5864
+ return /* @__PURE__ */ jsx(
5865
+ "tbody",
5866
+ {
5867
+ ref,
5868
+ "data-slot": "table-body",
5869
+ className: cn("[&_tr:last-child]:border-0", className),
5870
+ ...props
5871
+ }
5872
+ );
5873
+ }
5874
+ );
5875
+ TableBody.displayName = "TableBody";
5876
+ var TableFooter = React7.forwardRef(
5877
+ ({ className, ...props }, ref) => {
5878
+ return /* @__PURE__ */ jsx(
5879
+ "tfoot",
5880
+ {
5881
+ ref,
5882
+ "data-slot": "table-footer",
5883
+ className: cn(
5884
+ "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
5885
+ className
5886
+ ),
5887
+ ...props
5888
+ }
5889
+ );
5890
+ }
5891
+ );
5892
+ TableFooter.displayName = "TableFooter";
5643
5893
  var TableRow = React7.forwardRef(({ className, ...props }, ref) => {
5644
5894
  return /* @__PURE__ */ jsx(
5645
5895
  "tr",
@@ -5655,44 +5905,1350 @@ var TableRow = React7.forwardRef(({ className, ...props }, ref) => {
5655
5905
  );
5656
5906
  });
5657
5907
  TableRow.displayName = "TableRow";
5658
- function TableHead({ className, ...props }) {
5659
- return /* @__PURE__ */ jsx(
5660
- "th",
5661
- {
5662
- "data-slot": "table-head",
5663
- className: cn(
5664
- "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
5665
- className
5666
- ),
5667
- ...props
5668
- }
5669
- );
5670
- }
5671
- function TableCell({ className, ...props }) {
5672
- return /* @__PURE__ */ jsx(
5673
- "td",
5674
- {
5675
- "data-slot": "table-cell",
5676
- className: cn(
5677
- "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
5678
- className
5679
- ),
5680
- ...props
5681
- }
5682
- );
5683
- }
5684
- function TableCaption({
5685
- className,
5686
- ...props
5687
- }) {
5688
- return /* @__PURE__ */ jsx(
5689
- "caption",
5690
- {
5691
- "data-slot": "table-caption",
5692
- className: cn("text-muted-foreground mt-4 text-sm", className),
5693
- ...props
5694
- }
5695
- );
5908
+ var TableHead = React7.forwardRef(
5909
+ ({ className, ...props }, ref) => {
5910
+ return /* @__PURE__ */ jsx(
5911
+ "th",
5912
+ {
5913
+ ref,
5914
+ "data-slot": "table-head",
5915
+ className: cn(
5916
+ "text-foreground h-10 px-2 text-left align-middle font-medium",
5917
+ "[&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
5918
+ className
5919
+ ),
5920
+ ...props
5921
+ }
5922
+ );
5923
+ }
5924
+ );
5925
+ TableHead.displayName = "TableHead";
5926
+ var TableCell = React7.forwardRef(
5927
+ ({ className, ...props }, ref) => {
5928
+ return /* @__PURE__ */ jsx(
5929
+ "td",
5930
+ {
5931
+ ref,
5932
+ "data-slot": "table-cell",
5933
+ className: cn(
5934
+ "p-2 align-middle",
5935
+ "[&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
5936
+ className
5937
+ ),
5938
+ ...props
5939
+ }
5940
+ );
5941
+ }
5942
+ );
5943
+ TableCell.displayName = "TableCell";
5944
+ var TableCaption = React7.forwardRef(
5945
+ ({ className, ...props }, ref) => {
5946
+ return /* @__PURE__ */ jsx(
5947
+ "caption",
5948
+ {
5949
+ ref,
5950
+ "data-slot": "table-caption",
5951
+ className: cn("text-muted-foreground mt-4 text-sm", className),
5952
+ ...props
5953
+ }
5954
+ );
5955
+ }
5956
+ );
5957
+ TableCaption.displayName = "TableCaption";
5958
+ var defaultLabels = {
5959
+ previous: "Anterior",
5960
+ next: "Pr\xF3xima",
5961
+ first: "Primeira",
5962
+ last: "\xDAltima",
5963
+ showing: "Mostrando",
5964
+ of: "de",
5965
+ results: "resultados",
5966
+ itemsPerPage: "Itens por p\xE1gina",
5967
+ page: "P\xE1gina"
5968
+ };
5969
+ var defaultPageSizeOptions = [10, 20, 30, 50, 100];
5970
+ function getPageNumbers(currentPage, totalPages, maxVisible = 5) {
5971
+ if (totalPages <= maxVisible) {
5972
+ return Array.from({ length: totalPages }, (_, i) => i + 1);
5973
+ }
5974
+ const pages = [];
5975
+ const halfVisible = Math.floor(maxVisible / 2);
5976
+ pages.push(1);
5977
+ let start = Math.max(2, currentPage - halfVisible);
5978
+ let end = Math.min(totalPages - 1, currentPage + halfVisible);
5979
+ if (currentPage <= halfVisible + 1) {
5980
+ end = maxVisible - 1;
5981
+ } else if (currentPage >= totalPages - halfVisible) {
5982
+ start = totalPages - maxVisible + 2;
5983
+ }
5984
+ if (start > 2) {
5985
+ pages.push("ellipsis");
5986
+ }
5987
+ for (let i = start; i <= end; i++) {
5988
+ pages.push(i);
5989
+ }
5990
+ if (end < totalPages - 1) {
5991
+ pages.push("ellipsis");
5992
+ }
5993
+ if (totalPages > 1) {
5994
+ pages.push(totalPages);
5995
+ }
5996
+ return pages;
5997
+ }
5998
+ function TablePagination({
5999
+ currentPage,
6000
+ totalPages,
6001
+ pageSize,
6002
+ totalItems,
6003
+ onPageChange,
6004
+ onPageSizeChange,
6005
+ pageSizeOptions = defaultPageSizeOptions,
6006
+ maxVisiblePages = 5,
6007
+ showInfo = true,
6008
+ showPageNumbers = true,
6009
+ showPageSizeSelector = true,
6010
+ showFirstLastButtons = true,
6011
+ labels: customLabels,
6012
+ className
6013
+ }) {
6014
+ const labels = { ...defaultLabels, ...customLabels };
6015
+ const pages = getPageNumbers(currentPage, totalPages, maxVisiblePages);
6016
+ const startItem = (currentPage - 1) * pageSize + 1;
6017
+ const endItem = Math.min(currentPage * pageSize, totalItems);
6018
+ const hasPreviousPage = currentPage > 1;
6019
+ const hasNextPage = currentPage < totalPages;
6020
+ if (totalPages === 0) {
6021
+ return null;
6022
+ }
6023
+ return /* @__PURE__ */ jsxs(
6024
+ "div",
6025
+ {
6026
+ className: cn(
6027
+ "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
6028
+ className
6029
+ ),
6030
+ role: "navigation",
6031
+ "aria-label": "Pagina\xE7\xE3o da tabela",
6032
+ children: [
6033
+ showInfo && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground order-2 sm:order-1", children: [
6034
+ labels.showing,
6035
+ " ",
6036
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: startItem }),
6037
+ " - ",
6038
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: endItem }),
6039
+ " ",
6040
+ labels.of,
6041
+ " ",
6042
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: totalItems }),
6043
+ " ",
6044
+ labels.results
6045
+ ] }),
6046
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-4 order-1 sm:order-2", children: [
6047
+ showPageSizeSelector && onPageSizeChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6048
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground whitespace-nowrap", children: labels.itemsPerPage }),
6049
+ /* @__PURE__ */ jsxs(
6050
+ Select,
6051
+ {
6052
+ value: String(pageSize),
6053
+ onValueChange: (value) => onPageSizeChange(Number(value)),
6054
+ children: [
6055
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "h-8 w-[70px]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: pageSize }) }),
6056
+ /* @__PURE__ */ jsx(SelectContent, { children: pageSizeOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: String(option), children: option }, option)) })
6057
+ ]
6058
+ }
6059
+ )
6060
+ ] }),
6061
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground sm:hidden", children: [
6062
+ labels.page,
6063
+ " ",
6064
+ currentPage,
6065
+ " ",
6066
+ labels.of,
6067
+ " ",
6068
+ totalPages
6069
+ ] }),
6070
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
6071
+ showFirstLastButtons && /* @__PURE__ */ jsx(
6072
+ Button,
6073
+ {
6074
+ variant: "outline",
6075
+ size: "icon",
6076
+ className: "h-8 w-8",
6077
+ onClick: () => onPageChange(1),
6078
+ disabled: !hasPreviousPage,
6079
+ "aria-label": labels.first,
6080
+ children: /* @__PURE__ */ jsx(ChevronsLeft, { className: "h-4 w-4" })
6081
+ }
6082
+ ),
6083
+ /* @__PURE__ */ jsx(
6084
+ Button,
6085
+ {
6086
+ variant: "outline",
6087
+ size: "icon",
6088
+ className: "h-8 w-8",
6089
+ onClick: () => onPageChange(currentPage - 1),
6090
+ disabled: !hasPreviousPage,
6091
+ "aria-label": labels.previous,
6092
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
6093
+ }
6094
+ ),
6095
+ showPageNumbers && /* @__PURE__ */ jsx("div", { className: "hidden sm:flex items-center gap-1", children: pages.map(
6096
+ (page, index) => page === "ellipsis" ? /* @__PURE__ */ jsx(
6097
+ "span",
6098
+ {
6099
+ className: "flex items-center justify-center w-8 h-8 text-muted-foreground",
6100
+ "aria-hidden": true,
6101
+ children: "..."
6102
+ },
6103
+ `ellipsis-${index}`
6104
+ ) : /* @__PURE__ */ jsx(
6105
+ Button,
6106
+ {
6107
+ variant: currentPage === page ? "default" : "outline",
6108
+ size: "icon",
6109
+ className: "h-8 w-8",
6110
+ onClick: () => onPageChange(page),
6111
+ "aria-label": `${labels.page} ${page}`,
6112
+ "aria-current": currentPage === page ? "page" : void 0,
6113
+ children: page
6114
+ },
6115
+ page
6116
+ )
6117
+ ) }),
6118
+ /* @__PURE__ */ jsx(
6119
+ Button,
6120
+ {
6121
+ variant: "outline",
6122
+ size: "icon",
6123
+ className: "h-8 w-8",
6124
+ onClick: () => onPageChange(currentPage + 1),
6125
+ disabled: !hasNextPage,
6126
+ "aria-label": labels.next,
6127
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
6128
+ }
6129
+ ),
6130
+ showFirstLastButtons && /* @__PURE__ */ jsx(
6131
+ Button,
6132
+ {
6133
+ variant: "outline",
6134
+ size: "icon",
6135
+ className: "h-8 w-8",
6136
+ onClick: () => onPageChange(totalPages),
6137
+ disabled: !hasNextPage,
6138
+ "aria-label": labels.last,
6139
+ children: /* @__PURE__ */ jsx(ChevronsRight, { className: "h-4 w-4" })
6140
+ }
6141
+ )
6142
+ ] })
6143
+ ] })
6144
+ ]
6145
+ }
6146
+ );
6147
+ }
6148
+ TablePagination.displayName = "TablePagination";
6149
+
6150
+ // components/ui/table-types.ts
6151
+ function calculatePaginationMetadata(config) {
6152
+ const { currentPage, pageSize, totalItems } = config;
6153
+ const totalPages = Math.ceil(totalItems / pageSize);
6154
+ const startIndex = (currentPage - 1) * pageSize;
6155
+ const endIndex = Math.min(startIndex + pageSize, totalItems);
6156
+ return {
6157
+ totalPages,
6158
+ startIndex,
6159
+ endIndex,
6160
+ hasNextPage: currentPage < totalPages,
6161
+ hasPreviousPage: currentPage > 1
6162
+ };
6163
+ }
6164
+ function useTablePagination({
6165
+ data,
6166
+ initialPageSize = 10,
6167
+ resetOnDataChange = true
6168
+ }) {
6169
+ const [currentPage, setCurrentPage] = useState(1);
6170
+ const [pageSize, setPageSize] = useState(initialPageSize);
6171
+ useMemo(() => {
6172
+ if (resetOnDataChange) {
6173
+ setCurrentPage(1);
6174
+ }
6175
+ }, [data.length, resetOnDataChange]);
6176
+ const totalItems = data.length;
6177
+ const totalPages = Math.ceil(totalItems / pageSize);
6178
+ const safeCurrentPage = Math.min(Math.max(1, currentPage), Math.max(1, totalPages));
6179
+ const startIndex = (safeCurrentPage - 1) * pageSize;
6180
+ const endIndex = Math.min(startIndex + pageSize, totalItems);
6181
+ const paginatedData = useMemo(() => {
6182
+ return data.slice(startIndex, endIndex);
6183
+ }, [data, startIndex, endIndex]);
6184
+ const goToPage = (page) => {
6185
+ const targetPage = Math.max(1, Math.min(page, totalPages));
6186
+ setCurrentPage(targetPage);
6187
+ };
6188
+ const nextPage = () => {
6189
+ if (currentPage < totalPages) {
6190
+ setCurrentPage((p) => p + 1);
6191
+ }
6192
+ };
6193
+ const prevPage = () => {
6194
+ if (currentPage > 1) {
6195
+ setCurrentPage((p) => p - 1);
6196
+ }
6197
+ };
6198
+ const handleSetPageSize = (newSize) => {
6199
+ setPageSize(newSize);
6200
+ setCurrentPage(1);
6201
+ };
6202
+ const paginationConfig = {
6203
+ currentPage: safeCurrentPage,
6204
+ pageSize,
6205
+ totalItems,
6206
+ onPageChange: goToPage,
6207
+ onPageSizeChange: handleSetPageSize
6208
+ };
6209
+ const metadata = calculatePaginationMetadata(paginationConfig);
6210
+ return {
6211
+ currentPage: safeCurrentPage,
6212
+ pageSize,
6213
+ totalItems,
6214
+ totalPages,
6215
+ paginatedData,
6216
+ goToPage,
6217
+ nextPage,
6218
+ prevPage,
6219
+ setPageSize: handleSetPageSize,
6220
+ paginationConfig,
6221
+ metadata
6222
+ };
6223
+ }
6224
+
6225
+ // hooks/use-data-table.ts
6226
+ function useDataTable({
6227
+ data,
6228
+ initialSort = { column: null, direction: null },
6229
+ initialPageSize = 10,
6230
+ enablePagination = true
6231
+ }) {
6232
+ const [sortConfig, setSortConfig] = useState(initialSort);
6233
+ const [filters, setFilters] = useState([]);
6234
+ const filteredData = useMemo(() => {
6235
+ if (filters.length === 0) return data;
6236
+ return data.filter((item) => {
6237
+ return filters.every((filter) => {
6238
+ const itemValue = item[filter.column];
6239
+ switch (filter.operator) {
6240
+ case "equals":
6241
+ return itemValue == filter.value;
6242
+ case "contains":
6243
+ return String(itemValue).toLowerCase().includes(String(filter.value).toLowerCase());
6244
+ case "startsWith":
6245
+ return String(itemValue).toLowerCase().startsWith(String(filter.value).toLowerCase());
6246
+ case "greaterThan":
6247
+ return itemValue > filter.value;
6248
+ case "lessThan":
6249
+ return itemValue < filter.value;
6250
+ default:
6251
+ return true;
6252
+ }
6253
+ });
6254
+ });
6255
+ }, [data, filters]);
6256
+ const sortedData = useMemo(() => {
6257
+ if (!sortConfig.column || !sortConfig.direction) return filteredData;
6258
+ return [...filteredData].sort((a, b) => {
6259
+ const aValue = a[sortConfig.column];
6260
+ const bValue = b[sortConfig.column];
6261
+ if (aValue < bValue) return sortConfig.direction === "asc" ? -1 : 1;
6262
+ if (aValue > bValue) return sortConfig.direction === "asc" ? 1 : -1;
6263
+ return 0;
6264
+ });
6265
+ }, [filteredData, sortConfig]);
6266
+ const pagination = useTablePagination({
6267
+ data: sortedData,
6268
+ initialPageSize,
6269
+ resetOnDataChange: true
6270
+ // Reset to page 1 if filters change
6271
+ });
6272
+ const handleSort = (column) => {
6273
+ setSortConfig((current) => {
6274
+ if (current.column === column) {
6275
+ if (current.direction === "asc") return { column, direction: "desc" };
6276
+ if (current.direction === "desc") return { column: null, direction: null };
6277
+ }
6278
+ return { column, direction: "asc" };
6279
+ });
6280
+ };
6281
+ const setFilter = (column, value, operator = "contains") => {
6282
+ setFilters((prev) => {
6283
+ const existing = prev.filter((f) => f.column !== column);
6284
+ if (value === "" || value === null || value === void 0) {
6285
+ return existing;
6286
+ }
6287
+ return [...existing, { column, operator, value }];
6288
+ });
6289
+ };
6290
+ const removeFilter = (column) => {
6291
+ setFilters((prev) => prev.filter((f) => f.column !== column));
6292
+ };
6293
+ const getSortDirection = (column) => {
6294
+ return sortConfig.column === column ? sortConfig.direction : null;
6295
+ };
6296
+ return {
6297
+ data: enablePagination ? pagination.paginatedData : sortedData,
6298
+ state: {
6299
+ sort: sortConfig,
6300
+ filters,
6301
+ pagination: pagination.paginationConfig
6302
+ },
6303
+ handlers: {
6304
+ onSort: handleSort,
6305
+ setFilter,
6306
+ removeFilter,
6307
+ clearFilters: () => setFilters([])
6308
+ },
6309
+ getSortDirection
6310
+ };
6311
+ }
6312
+ function FilterChip({ label, value, onRemove, className }) {
6313
+ return /* @__PURE__ */ jsxs(
6314
+ Badge,
6315
+ {
6316
+ variant: "secondary",
6317
+ className: cn(
6318
+ "gap-1 pr-1 pl-2 h-7",
6319
+ onRemove && "pr-1",
6320
+ className
6321
+ ),
6322
+ children: [
6323
+ /* @__PURE__ */ jsxs("span", { className: "text-sm", children: [
6324
+ label,
6325
+ value && /* @__PURE__ */ jsxs(Fragment, { children: [
6326
+ ": ",
6327
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: value })
6328
+ ] })
6329
+ ] }),
6330
+ onRemove && /* @__PURE__ */ jsx(
6331
+ "button",
6332
+ {
6333
+ type: "button",
6334
+ onClick: onRemove,
6335
+ className: "ml-1 rounded-sm hover:bg-muted p-0.5 transition-colors",
6336
+ "aria-label": `Remove ${label} filter`,
6337
+ children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
6338
+ }
6339
+ )
6340
+ ]
6341
+ }
6342
+ );
6343
+ }
6344
+ function FilterBar({
6345
+ activeFilters = [],
6346
+ onClearAll,
6347
+ onOpenFilters,
6348
+ className,
6349
+ children
6350
+ }) {
6351
+ const hasFilters = activeFilters.length > 0;
6352
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2 flex-wrap", className), children: [
6353
+ /* @__PURE__ */ jsxs(
6354
+ Button,
6355
+ {
6356
+ variant: "outline",
6357
+ size: "sm",
6358
+ onClick: onOpenFilters,
6359
+ className: "gap-2",
6360
+ children: [
6361
+ /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4" }),
6362
+ "Filters",
6363
+ hasFilters && /* @__PURE__ */ jsx("span", { className: "ml-1 rounded-full bg-primary text-primary-foreground w-5 h-5 text-xs flex items-center justify-center", children: activeFilters.length })
6364
+ ]
6365
+ }
6366
+ ),
6367
+ hasFilters && /* @__PURE__ */ jsxs(Fragment, { children: [
6368
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-border" }),
6369
+ activeFilters.map((filter) => /* @__PURE__ */ jsx(
6370
+ FilterChip,
6371
+ {
6372
+ label: filter.label,
6373
+ value: filter.value,
6374
+ onRemove: filter.onRemove
6375
+ },
6376
+ filter.id
6377
+ )),
6378
+ /* @__PURE__ */ jsxs(
6379
+ Button,
6380
+ {
6381
+ variant: "ghost",
6382
+ size: "sm",
6383
+ onClick: onClearAll,
6384
+ className: "gap-1 h-7 px-2",
6385
+ children: [
6386
+ /* @__PURE__ */ jsx(X, { className: "h-3 w-3" }),
6387
+ "Clear all"
6388
+ ]
6389
+ }
6390
+ )
6391
+ ] }),
6392
+ children
6393
+ ] });
6394
+ }
6395
+ var OPERATORS = [
6396
+ { value: "is", label: "\xE9", multiSelect: false },
6397
+ { value: "is_not", label: "n\xE3o \xE9", multiSelect: false },
6398
+ { value: "is_any_of", label: "\xE9 qualquer um de", multiSelect: true },
6399
+ { value: "is_none_of", label: "n\xE3o \xE9 nenhum de", multiSelect: true },
6400
+ { value: "contains", label: "cont\xE9m", multiSelect: false },
6401
+ { value: "does_not_contain", label: "n\xE3o cont\xE9m", multiSelect: false },
6402
+ { value: "greater_than", label: "maior que", multiSelect: false },
6403
+ { value: "less_than", label: "menor que", multiSelect: false },
6404
+ { value: "is_empty", label: "est\xE1 vazio", multiSelect: false },
6405
+ { value: "is_not_empty", label: "n\xE3o est\xE1 vazio", multiSelect: false }
6406
+ ];
6407
+ function FilterBuilder({
6408
+ conditions,
6409
+ onConditionsChange,
6410
+ fields,
6411
+ className
6412
+ }) {
6413
+ const addCondition = () => {
6414
+ const newCondition = {
6415
+ id: Math.random().toString(36).substr(2, 9),
6416
+ field: fields[0]?.value || "",
6417
+ operator: "is",
6418
+ value: ""
6419
+ };
6420
+ onConditionsChange([...conditions, newCondition]);
6421
+ };
6422
+ const removeCondition = (id) => {
6423
+ onConditionsChange(conditions.filter((c) => c.id !== id));
6424
+ };
6425
+ const updateCondition = (id, updates) => {
6426
+ onConditionsChange(
6427
+ conditions.map((c) => c.id === id ? { ...c, ...updates } : c)
6428
+ );
6429
+ };
6430
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
6431
+ conditions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-8 text-muted-foreground text-sm", children: 'Nenhuma condi\xE7\xE3o de filtro. Clique em "Adicionar condi\xE7\xE3o" para come\xE7ar.' }) : conditions.map((condition, index) => /* @__PURE__ */ jsx(
6432
+ ConditionRow,
6433
+ {
6434
+ condition,
6435
+ fields,
6436
+ index,
6437
+ onUpdate: (updates) => updateCondition(condition.id, updates),
6438
+ onRemove: () => removeCondition(condition.id)
6439
+ },
6440
+ condition.id
6441
+ )),
6442
+ /* @__PURE__ */ jsxs(
6443
+ Button,
6444
+ {
6445
+ type: "button",
6446
+ variant: "outline",
6447
+ size: "sm",
6448
+ onClick: addCondition,
6449
+ className: "gap-2",
6450
+ children: [
6451
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
6452
+ "Adicionar condi\xE7\xE3o"
6453
+ ]
6454
+ }
6455
+ )
6456
+ ] });
6457
+ }
6458
+ function ConditionRow({
6459
+ condition,
6460
+ fields,
6461
+ index,
6462
+ onUpdate,
6463
+ onRemove
6464
+ }) {
6465
+ const selectedField = fields.find((f) => f.value === condition.field);
6466
+ const selectedOperator = OPERATORS.find((op) => op.value === condition.operator);
6467
+ const isMultiSelect = selectedField?.multiSelect || selectedOperator?.multiSelect || false;
6468
+ const needsValue = !["is_empty", "is_not_empty"].includes(condition.operator);
6469
+ const valueAsArray = Array.isArray(condition.value) ? condition.value : condition.value ? [condition.value] : [];
6470
+ const toggleValue = (val) => {
6471
+ if (!isMultiSelect) {
6472
+ onUpdate({ value: val });
6473
+ return;
6474
+ }
6475
+ const currentValues = Array.isArray(condition.value) ? condition.value : [];
6476
+ const newValues = currentValues.includes(val) ? currentValues.filter((v) => v !== val) : [...currentValues, val];
6477
+ onUpdate({ value: newValues });
6478
+ };
6479
+ const removeValue = (val) => {
6480
+ if (!isMultiSelect) return;
6481
+ const currentValues = Array.isArray(condition.value) ? condition.value : [];
6482
+ onUpdate({ value: currentValues.filter((v) => v !== val) });
6483
+ };
6484
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 group", children: [
6485
+ /* @__PURE__ */ jsx("div", { className: "flex items-center h-9 px-2 text-sm text-muted-foreground", children: index === 0 ? "Onde" : "E" }),
6486
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex items-center gap-2 flex-wrap p-2 border rounded-lg bg-background", children: [
6487
+ /* @__PURE__ */ jsxs(Popover, { children: [
6488
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6489
+ Button,
6490
+ {
6491
+ variant: "ghost",
6492
+ size: "sm",
6493
+ className: "h-7 px-2 font-normal hover:bg-muted",
6494
+ children: selectedField?.label || "Selecionar campo"
6495
+ }
6496
+ ) }),
6497
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[200px] p-2", align: "start", children: /* @__PURE__ */ jsx("div", { className: "space-y-1", children: fields.map((field) => /* @__PURE__ */ jsx(
6498
+ Button,
6499
+ {
6500
+ variant: "ghost",
6501
+ size: "sm",
6502
+ className: cn(
6503
+ "w-full justify-start",
6504
+ condition.field === field.value && "bg-muted"
6505
+ ),
6506
+ onClick: () => onUpdate({
6507
+ field: field.value,
6508
+ value: field.multiSelect ? [] : ""
6509
+ }),
6510
+ children: field.label
6511
+ },
6512
+ field.value
6513
+ )) }) })
6514
+ ] }),
6515
+ /* @__PURE__ */ jsxs(Popover, { children: [
6516
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6517
+ Button,
6518
+ {
6519
+ variant: "ghost",
6520
+ size: "sm",
6521
+ className: "h-7 px-2 font-normal hover:bg-muted text-muted-foreground",
6522
+ children: selectedOperator?.label || "is"
6523
+ }
6524
+ ) }),
6525
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[200px] p-2", align: "start", children: /* @__PURE__ */ jsx("div", { className: "space-y-1", children: OPERATORS.map((op) => /* @__PURE__ */ jsx(
6526
+ Button,
6527
+ {
6528
+ variant: "ghost",
6529
+ size: "sm",
6530
+ className: cn(
6531
+ "w-full justify-start",
6532
+ condition.operator === op.value && "bg-muted"
6533
+ ),
6534
+ onClick: () => onUpdate({
6535
+ operator: op.value,
6536
+ value: op.multiSelect ? [] : ""
6537
+ }),
6538
+ children: op.label
6539
+ },
6540
+ op.value
6541
+ )) }) })
6542
+ ] }),
6543
+ needsValue && /* @__PURE__ */ jsxs(Fragment, { children: [
6544
+ selectedField?.options ? (
6545
+ // Select field with options
6546
+ /* @__PURE__ */ jsxs(Popover, { children: [
6547
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6548
+ Button,
6549
+ {
6550
+ variant: "ghost",
6551
+ size: "sm",
6552
+ className: "h-7 px-2 font-normal hover:bg-muted",
6553
+ children: isMultiSelect && valueAsArray.length > 0 ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
6554
+ valueAsArray.length,
6555
+ " selecionado",
6556
+ valueAsArray.length > 1 ? "s" : ""
6557
+ ] }) : !isMultiSelect && condition.value ? selectedField.options.find(
6558
+ (opt) => opt.value === condition.value
6559
+ )?.label || "Selecionar valor" : "Selecionar valor"
6560
+ }
6561
+ ) }),
6562
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[240px] p-3", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
6563
+ /* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground", children: isMultiSelect ? "Selecionar valores" : "Selecionar valor" }),
6564
+ /* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-[200px] overflow-y-auto", children: selectedField.options.map((option) => {
6565
+ const isSelected = isMultiSelect ? valueAsArray.includes(option.value) : condition.value === option.value;
6566
+ return /* @__PURE__ */ jsx(
6567
+ "div",
6568
+ {
6569
+ className: "flex items-center space-x-2",
6570
+ children: isMultiSelect ? /* @__PURE__ */ jsxs(Fragment, { children: [
6571
+ /* @__PURE__ */ jsx(
6572
+ Checkbox,
6573
+ {
6574
+ id: `${condition.id}-${option.value}`,
6575
+ checked: isSelected,
6576
+ onCheckedChange: () => toggleValue(option.value)
6577
+ }
6578
+ ),
6579
+ /* @__PURE__ */ jsx(
6580
+ "label",
6581
+ {
6582
+ htmlFor: `${condition.id}-${option.value}`,
6583
+ className: "text-sm cursor-pointer flex-1",
6584
+ children: option.label
6585
+ }
6586
+ )
6587
+ ] }) : /* @__PURE__ */ jsx(
6588
+ Button,
6589
+ {
6590
+ variant: "ghost",
6591
+ size: "sm",
6592
+ className: cn(
6593
+ "w-full justify-start",
6594
+ isSelected && "bg-muted"
6595
+ ),
6596
+ onClick: () => onUpdate({ value: option.value }),
6597
+ children: option.label
6598
+ }
6599
+ )
6600
+ },
6601
+ option.value
6602
+ );
6603
+ }) })
6604
+ ] }) })
6605
+ ] })
6606
+ ) : (
6607
+ // Text/Number input
6608
+ /* @__PURE__ */ jsxs(Popover, { children: [
6609
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6610
+ Button,
6611
+ {
6612
+ variant: "ghost",
6613
+ size: "sm",
6614
+ className: "h-7 px-2 font-normal hover:bg-muted max-w-[200px] truncate",
6615
+ children: condition.value || "Inserir valor"
6616
+ }
6617
+ ) }),
6618
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[240px] p-3", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
6619
+ /* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground", children: "Inserir valor" }),
6620
+ /* @__PURE__ */ jsx(
6621
+ Input,
6622
+ {
6623
+ type: selectedField?.type === "number" ? "number" : "text",
6624
+ value: Array.isArray(condition.value) ? "" : condition.value,
6625
+ onChange: (e) => onUpdate({ value: e.target.value }),
6626
+ placeholder: "Digite o valor...",
6627
+ autoFocus: true
6628
+ }
6629
+ )
6630
+ ] }) })
6631
+ ] })
6632
+ ),
6633
+ isMultiSelect && valueAsArray.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 flex-wrap", children: valueAsArray.map((val) => {
6634
+ const optionLabel = selectedField?.options?.find((opt) => opt.value === val)?.label || val;
6635
+ return /* @__PURE__ */ jsxs(
6636
+ Badge,
6637
+ {
6638
+ variant: "secondary",
6639
+ className: "gap-1 h-6 text-xs",
6640
+ children: [
6641
+ optionLabel,
6642
+ /* @__PURE__ */ jsx(
6643
+ "button",
6644
+ {
6645
+ type: "button",
6646
+ onClick: () => removeValue(val),
6647
+ className: "ml-1 rounded-sm hover:bg-muted p-0.5 transition-colors",
6648
+ "aria-label": `Remover ${optionLabel}`,
6649
+ children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
6650
+ }
6651
+ )
6652
+ ]
6653
+ },
6654
+ val
6655
+ );
6656
+ }) })
6657
+ ] })
6658
+ ] }),
6659
+ /* @__PURE__ */ jsx(
6660
+ Button,
6661
+ {
6662
+ type: "button",
6663
+ variant: "ghost",
6664
+ size: "sm",
6665
+ onClick: onRemove,
6666
+ className: "h-9 w-9 p-0 opacity-0 group-hover:opacity-100 transition-opacity",
6667
+ "aria-label": "Remover condi\xE7\xE3o",
6668
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
6669
+ }
6670
+ )
6671
+ ] });
6672
+ }
6673
+ function DataTable({
6674
+ data,
6675
+ columns,
6676
+ searchPlaceholder = "Buscar...",
6677
+ searchableColumns,
6678
+ enableSearch = true,
6679
+ filterFields = [],
6680
+ enableFilters = false,
6681
+ pageSizeOptions = [5, 10, 20, 50],
6682
+ initialPageSize = 10,
6683
+ toolbarActions,
6684
+ className
6685
+ }) {
6686
+ const {
6687
+ data: processedData,
6688
+ state,
6689
+ handlers,
6690
+ getSortDirection
6691
+ } = useDataTable({
6692
+ data,
6693
+ initialPageSize,
6694
+ initialSort: { column: null, direction: null }
6695
+ });
6696
+ const [searchQuery, setSearchQuery] = useState("");
6697
+ const [filterDialogOpen, setFilterDialogOpen] = useState(false);
6698
+ const [advancedFilters, setAdvancedFilters] = useState([]);
6699
+ const defaultSearchColumn = searchableColumns ? searchableColumns[0] : columns.find((c) => c.key === "nome" || c.key === "name" || c.key === "title" || c.key === "titulo")?.key || columns[0]?.key;
6700
+ const handleSearchChange = (value) => {
6701
+ setSearchQuery(value);
6702
+ handlers.setFilter(defaultSearchColumn, value, "contains");
6703
+ };
6704
+ const activeFilterChips = advancedFilters.map((filter) => {
6705
+ const field = filterFields.find((f) => f.value === filter.field);
6706
+ const operatorLabel = filter.operator === "is" ? "" : ` ${filter.operator}`;
6707
+ const valueLabel = Array.isArray(filter.value) ? filter.value.join(", ") : filter.value;
6708
+ return {
6709
+ id: filter.id,
6710
+ label: field?.label || filter.field,
6711
+ value: `${operatorLabel} ${valueLabel}`.trim(),
6712
+ onRemove: () => {
6713
+ const updated = advancedFilters.filter((f) => f.id !== filter.id);
6714
+ setAdvancedFilters(updated);
6715
+ applyAdvancedFilters(updated);
6716
+ }
6717
+ };
6718
+ });
6719
+ const applyAdvancedFilters = (filters) => {
6720
+ handlers.clearFilters();
6721
+ if (searchQuery) {
6722
+ handlers.setFilter(defaultSearchColumn, searchQuery, "contains");
6723
+ }
6724
+ filters.forEach((filter) => {
6725
+ const operator = mapFilterOperator(filter.operator);
6726
+ handlers.setFilter(filter.field, filter.value, operator);
6727
+ });
6728
+ };
6729
+ const mapFilterOperator = (operator) => {
6730
+ switch (operator) {
6731
+ case "is":
6732
+ return "equals";
6733
+ case "contains":
6734
+ return "contains";
6735
+ case "starts_with":
6736
+ return "startsWith";
6737
+ case "greater_than":
6738
+ return "greaterThan";
6739
+ case "less_than":
6740
+ return "lessThan";
6741
+ default:
6742
+ return "contains";
6743
+ }
6744
+ };
6745
+ const handleApplyFilters = () => {
6746
+ applyAdvancedFilters(advancedFilters);
6747
+ setFilterDialogOpen(false);
6748
+ };
6749
+ const handleClearAllFilters = () => {
6750
+ setAdvancedFilters([]);
6751
+ handlers.clearFilters();
6752
+ if (searchQuery) {
6753
+ handlers.setFilter(defaultSearchColumn, searchQuery, "contains");
6754
+ }
6755
+ };
6756
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
6757
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
6758
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-1", children: [
6759
+ enableSearch && /* @__PURE__ */ jsxs("div", { className: "relative max-w-sm flex-1", children: [
6760
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground pointer-events-none" }),
6761
+ /* @__PURE__ */ jsx(
6762
+ Input,
6763
+ {
6764
+ placeholder: searchPlaceholder,
6765
+ value: searchQuery,
6766
+ onChange: (event) => handleSearchChange(event.target.value),
6767
+ className: "pl-9"
6768
+ }
6769
+ )
6770
+ ] }),
6771
+ enableFilters && filterFields.length > 0 && /* @__PURE__ */ jsxs(Popover, { open: filterDialogOpen, onOpenChange: setFilterDialogOpen, children: [
6772
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "gap-2", children: [
6773
+ /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4" }),
6774
+ "Filtros",
6775
+ advancedFilters.length > 0 && /* @__PURE__ */ jsx("span", { className: "ml-1 rounded-full bg-primary text-primary-foreground w-5 h-5 text-xs flex items-center justify-center", children: advancedFilters.length })
6776
+ ] }) }),
6777
+ /* @__PURE__ */ jsxs(PopoverContent, { className: "w-[700px] p-0", align: "start", sideOffset: 8, children: [
6778
+ /* @__PURE__ */ jsxs("div", { className: "p-6 border-b", children: [
6779
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold", children: "Filtros Avan\xE7ados" }),
6780
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Adicione condi\xE7\xF5es de filtro para refinar os resultados." })
6781
+ ] }),
6782
+ /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsx(
6783
+ FilterBuilder,
6784
+ {
6785
+ conditions: advancedFilters,
6786
+ onConditionsChange: setAdvancedFilters,
6787
+ fields: filterFields
6788
+ }
6789
+ ) }),
6790
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 p-4 border-t bg-muted/50", children: [
6791
+ /* @__PURE__ */ jsx(
6792
+ Button,
6793
+ {
6794
+ variant: "outline",
6795
+ size: "sm",
6796
+ onClick: () => setFilterDialogOpen(false),
6797
+ children: "Cancelar"
6798
+ }
6799
+ ),
6800
+ /* @__PURE__ */ jsx(
6801
+ Button,
6802
+ {
6803
+ size: "sm",
6804
+ onClick: handleApplyFilters,
6805
+ children: "Aplicar Filtros"
6806
+ }
6807
+ )
6808
+ ] })
6809
+ ] })
6810
+ ] })
6811
+ ] }),
6812
+ toolbarActions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: toolbarActions })
6813
+ ] }),
6814
+ advancedFilters.length > 0 && /* @__PURE__ */ jsx(
6815
+ FilterBar,
6816
+ {
6817
+ activeFilters: activeFilterChips,
6818
+ onClearAll: handleClearAllFilters
6819
+ }
6820
+ ),
6821
+ /* @__PURE__ */ jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs(Table, { children: [
6822
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx(
6823
+ TableHead,
6824
+ {
6825
+ className: cn(
6826
+ column.headerClassName,
6827
+ column.sortable && "cursor-pointer select-none hover:bg-muted/50 transition-colors"
6828
+ ),
6829
+ style: { width: column.width },
6830
+ onClick: () => column.sortable && handlers.onSort(column.key),
6831
+ "aria-sort": column.sortable ? getSortDirection(column.key) === "asc" ? "ascending" : getSortDirection(column.key) === "desc" ? "descending" : "none" : void 0,
6832
+ children: /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", column.align ? `justify-${column.align}` : "justify-start"), children: [
6833
+ column.header,
6834
+ column.sortable && /* @__PURE__ */ jsx(ArrowUpDown, { className: cn("h-4 w-4", getSortDirection(column.key) ? "opacity-100" : "opacity-40") })
6835
+ ] })
6836
+ },
6837
+ String(column.key)
6838
+ )) }) }),
6839
+ /* @__PURE__ */ jsx(TableBody, { children: processedData.length > 0 ? processedData.map((row, rowIndex) => /* @__PURE__ */ jsx(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx(
6840
+ TableCell,
6841
+ {
6842
+ className: cn(column.className, column.align ? `text-${column.align}` : "text-left"),
6843
+ children: column.render ? column.render(row[column.key], row, rowIndex) : row[column.key]
6844
+ },
6845
+ String(column.key)
6846
+ )) }, rowIndex)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
6847
+ TableCell,
6848
+ {
6849
+ colSpan: columns.length,
6850
+ className: "h-24 text-center",
6851
+ children: "Nenhum resultado encontrado."
6852
+ }
6853
+ ) }) })
6854
+ ] }) }),
6855
+ /* @__PURE__ */ jsx(
6856
+ TablePagination,
6857
+ {
6858
+ currentPage: state.pagination.currentPage,
6859
+ totalPages: Math.ceil(state.pagination.totalItems / state.pagination.pageSize),
6860
+ pageSize: state.pagination.pageSize,
6861
+ totalItems: state.pagination.totalItems,
6862
+ onPageChange: state.pagination.onPageChange || (() => {
6863
+ }),
6864
+ onPageSizeChange: state.pagination.onPageSizeChange,
6865
+ pageSizeOptions
6866
+ }
6867
+ )
6868
+ ] });
6869
+ }
6870
+ var sampleCampaigns = [
6871
+ {
6872
+ id: "1",
6873
+ name: "Campanha de Natal 2025",
6874
+ client: "Coca-Cola",
6875
+ status: "active",
6876
+ budget: 5e4,
6877
+ spent: 32e3,
6878
+ startDate: "2025-12-01",
6879
+ endDate: "2025-12-25"
6880
+ },
6881
+ {
6882
+ id: "2",
6883
+ name: "Black Friday Especial",
6884
+ client: "Nike",
6885
+ status: "completed",
6886
+ budget: 8e4,
6887
+ spent: 78500,
6888
+ startDate: "2025-11-15",
6889
+ endDate: "2025-11-30"
6890
+ },
6891
+ {
6892
+ id: "3",
6893
+ name: "Lan\xE7amento Produto X",
6894
+ client: "Apple",
6895
+ status: "active",
6896
+ budget: 12e4,
6897
+ spent: 45e3,
6898
+ startDate: "2025-12-05",
6899
+ endDate: "2026-01-15"
6900
+ },
6901
+ {
6902
+ id: "4",
6903
+ name: "Campanha Ver\xE3o",
6904
+ client: "Havaianas",
6905
+ status: "paused",
6906
+ budget: 35e3,
6907
+ spent: 18e3,
6908
+ startDate: "2025-11-20",
6909
+ endDate: "2026-02-28"
6910
+ },
6911
+ {
6912
+ id: "5",
6913
+ name: "Awareness Brand",
6914
+ client: "Google",
6915
+ status: "draft",
6916
+ budget: 95e3,
6917
+ spent: 0,
6918
+ startDate: "2026-01-01",
6919
+ endDate: "2026-03-31"
6920
+ },
6921
+ {
6922
+ id: "6",
6923
+ name: "Retargeting Q4",
6924
+ client: "Amazon",
6925
+ status: "active",
6926
+ budget: 65e3,
6927
+ spent: 42e3,
6928
+ startDate: "2025-10-01",
6929
+ endDate: "2025-12-31"
6930
+ },
6931
+ {
6932
+ id: "7",
6933
+ name: "Social Media Boost",
6934
+ client: "Nike",
6935
+ status: "active",
6936
+ budget: 28e3,
6937
+ spent: 15e3,
6938
+ startDate: "2025-11-01",
6939
+ endDate: "2025-12-31"
6940
+ },
6941
+ {
6942
+ id: "8",
6943
+ name: "Email Campaign",
6944
+ client: "Coca-Cola",
6945
+ status: "completed",
6946
+ budget: 12e3,
6947
+ spent: 11500,
6948
+ startDate: "2025-10-15",
6949
+ endDate: "2025-11-15"
6950
+ }
6951
+ ];
6952
+ function DataTableExample() {
6953
+ const [campaigns] = useState(sampleCampaigns);
6954
+ const columns = [
6955
+ {
6956
+ key: "name",
6957
+ header: "Campanha",
6958
+ sortable: true,
6959
+ width: "25%",
6960
+ className: "font-medium"
6961
+ },
6962
+ {
6963
+ key: "client",
6964
+ header: "Cliente",
6965
+ sortable: true
6966
+ },
6967
+ {
6968
+ key: "status",
6969
+ header: "Status",
6970
+ sortable: true,
6971
+ render: (value) => {
6972
+ const variants = {
6973
+ active: "default",
6974
+ paused: "secondary",
6975
+ completed: "outline",
6976
+ draft: "secondary"
6977
+ };
6978
+ const labels = {
6979
+ active: "Ativa",
6980
+ paused: "Pausada",
6981
+ completed: "Conclu\xEDda",
6982
+ draft: "Rascunho"
6983
+ };
6984
+ return /* @__PURE__ */ jsx(Badge, { variant: variants[value], children: labels[value] });
6985
+ }
6986
+ },
6987
+ {
6988
+ key: "budget",
6989
+ header: "Or\xE7amento",
6990
+ align: "right",
6991
+ sortable: true,
6992
+ render: (value) => `R$ ${value.toLocaleString("pt-BR")}`
6993
+ },
6994
+ {
6995
+ key: "spent",
6996
+ header: "Gasto",
6997
+ align: "right",
6998
+ sortable: true,
6999
+ render: (value, row) => {
7000
+ const spent = value;
7001
+ const budget = row.budget;
7002
+ const percentage = spent / budget * 100;
7003
+ const color = percentage > 90 ? "text-red-600" : percentage > 70 ? "text-orange-600" : "text-green-600";
7004
+ return /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
7005
+ /* @__PURE__ */ jsxs("div", { className: color, children: [
7006
+ "R$ ",
7007
+ spent.toLocaleString("pt-BR")
7008
+ ] }),
7009
+ /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
7010
+ percentage.toFixed(0),
7011
+ "%"
7012
+ ] })
7013
+ ] });
7014
+ }
7015
+ },
7016
+ {
7017
+ key: "startDate",
7018
+ header: "In\xEDcio",
7019
+ sortable: true,
7020
+ render: (value) => new Date(value).toLocaleDateString("pt-BR")
7021
+ },
7022
+ {
7023
+ key: "id",
7024
+ header: "A\xE7\xF5es",
7025
+ align: "right",
7026
+ width: "80px",
7027
+ render: (id, row) => /* @__PURE__ */ jsxs(DropdownMenu, { children: [
7028
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" }) }) }),
7029
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
7030
+ /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => console.log("View", row), children: "Ver detalhes" }),
7031
+ /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => console.log("Edit", row), children: "Editar" }),
7032
+ /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => console.log("Duplicate", row), children: "Duplicar" }),
7033
+ /* @__PURE__ */ jsx(
7034
+ DropdownMenuItem,
7035
+ {
7036
+ onClick: () => console.log("Delete", id),
7037
+ className: "text-destructive",
7038
+ children: "Excluir"
7039
+ }
7040
+ )
7041
+ ] })
7042
+ ] })
7043
+ }
7044
+ ];
7045
+ const filterFields = [
7046
+ {
7047
+ value: "status",
7048
+ label: "Status",
7049
+ type: "select",
7050
+ options: [
7051
+ { value: "active", label: "Ativa" },
7052
+ { value: "paused", label: "Pausada" },
7053
+ { value: "completed", label: "Conclu\xEDda" },
7054
+ { value: "draft", label: "Rascunho" }
7055
+ ],
7056
+ multiSelect: true
7057
+ // Allow selecting multiple statuses
7058
+ },
7059
+ {
7060
+ value: "client",
7061
+ label: "Cliente",
7062
+ type: "select",
7063
+ options: [
7064
+ { value: "Coca-Cola", label: "Coca-Cola" },
7065
+ { value: "Nike", label: "Nike" },
7066
+ { value: "Apple", label: "Apple" },
7067
+ { value: "Havaianas", label: "Havaianas" },
7068
+ { value: "Google", label: "Google" },
7069
+ { value: "Amazon", label: "Amazon" }
7070
+ ]
7071
+ },
7072
+ {
7073
+ value: "budget",
7074
+ label: "Or\xE7amento",
7075
+ type: "number"
7076
+ },
7077
+ {
7078
+ value: "startDate",
7079
+ label: "Data de In\xEDcio",
7080
+ type: "date"
7081
+ }
7082
+ ];
7083
+ const handleExport = () => {
7084
+ console.log("Exporting campaigns...", campaigns);
7085
+ };
7086
+ const handleCreateNew = () => {
7087
+ console.log("Creating new campaign...");
7088
+ };
7089
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6 p-6", children: [
7090
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
7091
+ /* @__PURE__ */ jsxs("div", { children: [
7092
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Campanhas" }),
7093
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-2", children: "Gerencie suas campanhas de publicidade e acompanhe o desempenho" })
7094
+ ] }),
7095
+ /* @__PURE__ */ jsxs(Button, { onClick: handleCreateNew, children: [
7096
+ /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
7097
+ "Nova Campanha"
7098
+ ] })
7099
+ ] }),
7100
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-4 gap-4", children: [
7101
+ /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
7102
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Total de Campanhas" }),
7103
+ /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold mt-1", children: campaigns.length })
7104
+ ] }),
7105
+ /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
7106
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Campanhas Ativas" }),
7107
+ /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold mt-1 text-green-600", children: campaigns.filter((c) => c.status === "active").length })
7108
+ ] }),
7109
+ /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
7110
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Or\xE7amento Total" }),
7111
+ /* @__PURE__ */ jsxs("div", { className: "text-2xl font-bold mt-1", children: [
7112
+ "R$ ",
7113
+ campaigns.reduce((sum, c) => sum + c.budget, 0).toLocaleString("pt-BR")
7114
+ ] })
7115
+ ] }),
7116
+ /* @__PURE__ */ jsxs(Card, { className: "p-4", children: [
7117
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "Total Gasto" }),
7118
+ /* @__PURE__ */ jsxs("div", { className: "text-2xl font-bold mt-1", children: [
7119
+ "R$ ",
7120
+ campaigns.reduce((sum, c) => sum + c.spent, 0).toLocaleString("pt-BR")
7121
+ ] })
7122
+ ] })
7123
+ ] }),
7124
+ /* @__PURE__ */ jsx(Card, { className: "p-6", children: /* @__PURE__ */ jsx(
7125
+ DataTable,
7126
+ {
7127
+ data: campaigns,
7128
+ columns,
7129
+ searchPlaceholder: "Buscar por campanha ou cliente...",
7130
+ searchableColumns: ["name", "client"],
7131
+ enableSearch: true,
7132
+ enableFilters: true,
7133
+ filterFields,
7134
+ initialPageSize: 10,
7135
+ pageSizeOptions: [5, 10, 20, 50],
7136
+ toolbarActions: /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: handleExport, children: [
7137
+ /* @__PURE__ */ jsx(Download, { className: "h-4 w-4 mr-2" }),
7138
+ "Exportar"
7139
+ ] }) })
7140
+ }
7141
+ ) }),
7142
+ /* @__PURE__ */ jsx(Card, { className: "p-4 bg-blue-50 dark:bg-blue-950/20 border-blue-200 dark:border-blue-900", children: /* @__PURE__ */ jsxs("div", { className: "text-sm", children: [
7143
+ /* @__PURE__ */ jsx("strong", { children: "\u{1F4A1} Dica:" }),
7144
+ ' Use o campo de busca para encontrar campanhas rapidamente. Use os filtros avan\xE7ados para combinar m\xFAltiplas condi\xE7\xF5es (ex: "Status = Ativa" E "Cliente = Nike").'
7145
+ ] }) })
7146
+ ] });
7147
+ }
7148
+ function SavedFilters({
7149
+ filters = [],
7150
+ onSelectFilter,
7151
+ onToggleFavorite,
7152
+ onDeleteFilter,
7153
+ className
7154
+ }) {
7155
+ const favoriteFilters = filters.filter((f) => f.isFavorite);
7156
+ const otherFilters = filters.filter((f) => !f.isFavorite);
7157
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
7158
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: cn("gap-2", className), children: [
7159
+ /* @__PURE__ */ jsx(Download, { className: "h-4 w-4" }),
7160
+ "Saved Filters",
7161
+ filters.length > 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
7162
+ "(",
7163
+ filters.length,
7164
+ ")"
7165
+ ] })
7166
+ ] }) }),
7167
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align: "start", className: "w-[280px]", children: filters.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-2 py-6 text-center text-sm text-muted-foreground", children: "No saved filters yet" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
7168
+ favoriteFilters.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
7169
+ /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground", children: "Favorites" }),
7170
+ favoriteFilters.map((filter) => /* @__PURE__ */ jsx(
7171
+ FilterMenuItem,
7172
+ {
7173
+ filter,
7174
+ onSelect: onSelectFilter,
7175
+ onToggleFavorite,
7176
+ onDelete: onDeleteFilter
7177
+ },
7178
+ filter.id
7179
+ )),
7180
+ otherFilters.length > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {})
7181
+ ] }),
7182
+ otherFilters.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
7183
+ favoriteFilters.length > 0 && /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground", children: "All Filters" }),
7184
+ otherFilters.map((filter) => /* @__PURE__ */ jsx(
7185
+ FilterMenuItem,
7186
+ {
7187
+ filter,
7188
+ onSelect: onSelectFilter,
7189
+ onToggleFavorite,
7190
+ onDelete: onDeleteFilter
7191
+ },
7192
+ filter.id
7193
+ ))
7194
+ ] })
7195
+ ] }) })
7196
+ ] });
7197
+ }
7198
+ function FilterMenuItem({
7199
+ filter,
7200
+ onSelect,
7201
+ onToggleFavorite,
7202
+ onDelete
7203
+ }) {
7204
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5 hover:bg-muted rounded-sm group", children: [
7205
+ /* @__PURE__ */ jsx(
7206
+ "button",
7207
+ {
7208
+ onClick: (e) => {
7209
+ e.stopPropagation();
7210
+ onToggleFavorite?.(filter.id);
7211
+ },
7212
+ className: "p-1 hover:bg-accent rounded-sm",
7213
+ children: /* @__PURE__ */ jsx(
7214
+ Star,
7215
+ {
7216
+ className: cn(
7217
+ "h-3.5 w-3.5",
7218
+ filter.isFavorite ? "fill-yellow-500 text-yellow-500" : "text-muted-foreground"
7219
+ )
7220
+ }
7221
+ )
7222
+ }
7223
+ ),
7224
+ /* @__PURE__ */ jsxs(
7225
+ "button",
7226
+ {
7227
+ onClick: () => onSelect?.(filter.id),
7228
+ className: "flex-1 text-left px-2",
7229
+ children: [
7230
+ /* @__PURE__ */ jsx("div", { className: "text-sm", children: filter.name }),
7231
+ filter.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: filter.description }),
7232
+ filter.filterCount !== void 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-0.5", children: [
7233
+ filter.filterCount,
7234
+ " ",
7235
+ filter.filterCount === 1 ? "filter" : "filters"
7236
+ ] })
7237
+ ]
7238
+ }
7239
+ ),
7240
+ /* @__PURE__ */ jsx(
7241
+ "button",
7242
+ {
7243
+ onClick: (e) => {
7244
+ e.stopPropagation();
7245
+ onDelete?.(filter.id);
7246
+ },
7247
+ className: "p-1 hover:bg-accent rounded-sm opacity-0 group-hover:opacity-100 transition-opacity",
7248
+ children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5 text-destructive" })
7249
+ }
7250
+ )
7251
+ ] });
5696
7252
  }
5697
7253
  function Tabs({
5698
7254
  className,
@@ -6252,6 +7808,6 @@ function ProposalTemplate({
6252
7808
  );
6253
7809
  }
6254
7810
 
6255
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppLayout, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar2 as Calendar, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContractPrint, ContractPrintPreview, ContractTemplate, DateRangePicker, DateTimePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyCalendarIllustration, EmptyInboxIllustration, EmptyProjectsIllustration, EmptySearchIllustration, ErrorStateIllustration, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Illustrations, ImageWithFallback, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, KanbanCard, Label, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverContent, PopoverTrigger, PrintFooter, PrintHeader, PrintInfoGrid, PrintSection, PrintSignature, PrintTable, Progress, ProposalTemplate, RadioGroup4 as RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Toaster as Sonner, SuccessStateIllustration, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, TimePicker, Toggle, ToggleGroup, ToggleGroupItem, Tooltip2 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UnderlineTabs, UnderlineTabsContent, UnderlineTabsList, UnderlineTabsTrigger, badgeVariants, buttonVariants, cn, dadosContratoExemplo, navigationMenuTriggerStyle, toggleVariants, useFormField, useIsMobile, usePrintContract, useSidebar };
7811
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppLayout, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar2 as Calendar, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ColorPicker, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, ContractPrint, ContractPrintPreview, ContractTemplate, DataTable, DataTableExample, DatePicker, DateRangePicker, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyCalendarIllustration, EmptyInboxIllustration, EmptyProjectsIllustration, EmptySearchIllustration, ErrorStateIllustration, FilterBar, FilterBuilder, FilterChip, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, HoverCard, HoverCardContent, HoverCardTrigger, Illustrations, ImageWithFallback, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, KanbanCard, Label, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverContent, PopoverTrigger, PrintFooter, PrintHeader, PrintInfoGrid, PrintSection, PrintSignature, PrintTable, Progress, ProposalTemplate, RadioGroup4 as RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, SavedFilters, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator5 as Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Toaster as Sonner, SuccessStateIllustration, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TablePagination, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, TimePicker, Toggle, ToggleGroup, ToggleGroupItem, Tooltip2 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UnderlineTabs, UnderlineTabsContent, UnderlineTabsList, UnderlineTabsTrigger, badgeVariants, buttonVariants, calculatePaginationMetadata, cn, dadosContratoExemplo, getPageNumbers, navigationMenuTriggerStyle, toggleVariants, useFormField, useIsMobile, usePrintContract, useSidebar };
6256
7812
  //# sourceMappingURL=index.js.map
6257
7813
  //# sourceMappingURL=index.js.map