@evolution-soft/ui 1.0.0 → 1.0.3

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.
Files changed (78) hide show
  1. package/cli/index.js +386 -0
  2. package/components/button-icon-lottie/index.tsx +46 -0
  3. package/components/fullscreen-mode/index.tsx +82 -0
  4. package/components/header/components/buttons.tsx +102 -0
  5. package/components/header/index.tsx +146 -0
  6. package/components/loading-default/index.tsx +90 -0
  7. package/components/lottie-icon/index.tsx +78 -0
  8. package/components/not-found-default/index.tsx +68 -0
  9. package/components/settings-modal/index.tsx +225 -0
  10. package/components/sidebar/index.tsx +645 -0
  11. package/components/subtitle/index.tsx +60 -0
  12. package/components/theme-transition/index.tsx +142 -0
  13. package/components/title/index.tsx +66 -0
  14. package/components/tooltip-indicator/index.tsx +30 -0
  15. package/components/ui/accordion.tsx +66 -0
  16. package/components/ui/alert-dialog.tsx +157 -0
  17. package/components/ui/alert.tsx +66 -0
  18. package/components/ui/aspect-ratio.tsx +11 -0
  19. package/components/ui/avatar.tsx +53 -0
  20. package/components/ui/badge.tsx +46 -0
  21. package/components/ui/breadcrumb.tsx +109 -0
  22. package/components/ui/button.tsx +58 -0
  23. package/components/ui/calendar.tsx +78 -0
  24. package/components/ui/card.tsx +92 -0
  25. package/components/ui/carousel.tsx +241 -0
  26. package/components/ui/chart.tsx +360 -0
  27. package/components/ui/checkbox.tsx +32 -0
  28. package/components/ui/collapsible.tsx +33 -0
  29. package/components/ui/command.tsx +177 -0
  30. package/components/ui/context-menu.tsx +252 -0
  31. package/components/ui/dialog.tsx +135 -0
  32. package/components/ui/divisor.tsx +9 -0
  33. package/components/ui/drawer.tsx +132 -0
  34. package/components/ui/dropdown-menu.tsx +257 -0
  35. package/components/ui/emoji-picker.tsx +76 -0
  36. package/components/ui/form.tsx +168 -0
  37. package/components/ui/hover-card.tsx +44 -0
  38. package/components/ui/input-mask.tsx +46 -0
  39. package/components/ui/input-otp.tsx +77 -0
  40. package/components/ui/input.tsx +61 -0
  41. package/components/ui/label.tsx +24 -0
  42. package/components/ui/menubar.tsx +276 -0
  43. package/components/ui/multiselect.tsx +105 -0
  44. package/components/ui/navigation-menu.tsx +168 -0
  45. package/components/ui/pagination.tsx +127 -0
  46. package/components/ui/popover.tsx +48 -0
  47. package/components/ui/progress.tsx +31 -0
  48. package/components/ui/radio-group.tsx +45 -0
  49. package/components/ui/resizable.tsx +65 -0
  50. package/components/ui/scroll-area.tsx +58 -0
  51. package/components/ui/searchable-select.tsx +211 -0
  52. package/components/ui/select.tsx +189 -0
  53. package/components/ui/separator.tsx +28 -0
  54. package/components/ui/sheet.tsx +139 -0
  55. package/components/ui/sidebar.tsx +727 -0
  56. package/components/ui/skeleton.tsx +144 -0
  57. package/components/ui/slider.tsx +63 -0
  58. package/components/ui/sonner.tsx +26 -0
  59. package/components/ui/switch.tsx +31 -0
  60. package/components/ui/table.tsx +116 -0
  61. package/components/ui/tabs.tsx +76 -0
  62. package/components/ui/textarea.tsx +18 -0
  63. package/components/ui/theme-toggle.tsx +89 -0
  64. package/components/ui/toggle-group.tsx +73 -0
  65. package/components/ui/toggle.tsx +47 -0
  66. package/components/ui/tooltip.tsx +61 -0
  67. package/components/ui/use-mobile.ts +21 -0
  68. package/components/ui/utils.ts +6 -0
  69. package/contexts/AnimationSettingsContext.tsx +85 -0
  70. package/contexts/AuthContext.tsx +80 -0
  71. package/contexts/ThemeContext.tsx +70 -0
  72. package/hooks/useAnimationSettings.ts +2 -0
  73. package/hooks/usePermissions.ts +4 -0
  74. package/lib/persistentFilters.ts +120 -0
  75. package/lib/utils.ts +2 -0
  76. package/package.json +11 -2
  77. package/stores/theme.ts +30 -0
  78. package/stores/useThemeStore.ts +32 -0
@@ -0,0 +1,144 @@
1
+ import { cn } from "./utils";
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn("bg-muted animate-pulse rounded-md", className)}
8
+ {...props}
9
+ />
10
+ );
11
+ }
12
+
13
+ interface TableSkeletonProps {
14
+ rows?: number;
15
+ columns?: number;
16
+ showHeader?: boolean;
17
+ className?: string;
18
+ }
19
+
20
+ function TableSkeleton({
21
+ rows = 5,
22
+ columns = 4,
23
+ showHeader = true,
24
+ className = ""
25
+ }: TableSkeletonProps) {
26
+ return (
27
+ <div className={cn("w-full", className)}>
28
+ <div className="bg-card border border-border rounded-lg overflow-hidden">
29
+ {/* Table Header */}
30
+ {showHeader && (
31
+ <div className="border-b border-border p-4">
32
+ <div className="grid gap-4" style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}>
33
+ {Array.from({ length: columns }).map((_, index) => (
34
+ <Skeleton key={index} className="h-3 w-[60%]" />
35
+ ))}
36
+ </div>
37
+ </div>
38
+ )}
39
+
40
+ {/* Table Rows */}
41
+ <div className="divide-y divide-border">
42
+ {Array.from({ length: rows }).map((_, rowIndex) => (
43
+ <div key={rowIndex} className="p-4">
44
+ <div className="grid gap-4" style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}>
45
+ {Array.from({ length: columns }).map((_, colIndex) => (
46
+ <Skeleton
47
+ key={colIndex}
48
+ className="h-4"
49
+ style={{
50
+ width: `${Math.random() * 40 + 40}%`,
51
+ animationDelay: `${(rowIndex * columns + colIndex) * 0.05}s`
52
+ }}
53
+ />
54
+ ))}
55
+ </div>
56
+ </div>
57
+ ))}
58
+ </div>
59
+ </div>
60
+ </div>
61
+ );
62
+ }
63
+
64
+ interface CardSkeletonProps {
65
+ showImage?: boolean;
66
+ showActions?: boolean;
67
+ className?: string;
68
+ }
69
+
70
+ function CardSkeleton({
71
+ showImage = false,
72
+ showActions = true,
73
+ className = ""
74
+ }: CardSkeletonProps) {
75
+ return (
76
+ <div className={cn("bg-card border border-border rounded-lg p-6 space-y-4", className)}>
77
+ {/* Image */}
78
+ {showImage && (
79
+ <Skeleton className="h-48 w-full" />
80
+ )}
81
+
82
+ {/* Header */}
83
+ <div className="space-y-2">
84
+ <Skeleton className="h-6 w-3/4" />
85
+ <Skeleton className="h-4 w-1/2" />
86
+ </div>
87
+
88
+ {/* Content */}
89
+ <div className="space-y-2">
90
+ <Skeleton className="h-4 w-full" />
91
+ <Skeleton className="h-4 w-[90%]" />
92
+ <Skeleton className="h-4 w-[80%]" />
93
+ </div>
94
+
95
+ {/* Actions */}
96
+ {showActions && (
97
+ <div className="flex justify-between items-center pt-4">
98
+ <div className="flex space-x-2">
99
+ <Skeleton className="h-8 w-16" />
100
+ <Skeleton className="h-8 w-16" />
101
+ </div>
102
+ <Skeleton className="h-8 w-20" />
103
+ </div>
104
+ )}
105
+ </div>
106
+ );
107
+ }
108
+
109
+ interface FormSkeletonProps {
110
+ fields?: number;
111
+ showButtons?: boolean;
112
+ className?: string;
113
+ }
114
+
115
+ function FormSkeleton({
116
+ fields = 4,
117
+ showButtons = true,
118
+ className = ""
119
+ }: FormSkeletonProps) {
120
+ return (
121
+ <div className={cn("bg-card border border-border rounded-lg p-6 space-y-6", className)}>
122
+ {/* Form Fields */}
123
+ {Array.from({ length: fields }).map((_, index) => (
124
+ <div key={index} className="space-y-2">
125
+ <Skeleton className="h-4 w-1/4" />
126
+ <Skeleton className="h-10 w-full" />
127
+ {index % 2 === 0 && (
128
+ <Skeleton className="h-3 w-3/5" />
129
+ )}
130
+ </div>
131
+ ))}
132
+
133
+ {/* Buttons */}
134
+ {showButtons && (
135
+ <div className="flex justify-end space-x-4 pt-4">
136
+ <Skeleton className="h-10 w-20" />
137
+ <Skeleton className="h-10 w-24" />
138
+ </div>
139
+ )}
140
+ </div>
141
+ );
142
+ }
143
+
144
+ export { Skeleton, TableSkeleton, CardSkeleton, FormSkeleton };
@@ -0,0 +1,63 @@
1
+
2
+
3
+ import * as React from "react";
4
+ import * as SliderPrimitive from "@radix-ui/react-slider";
5
+
6
+ import { cn } from "./utils";
7
+
8
+ function Slider({
9
+ className,
10
+ defaultValue,
11
+ value,
12
+ min = 0,
13
+ max = 100,
14
+ ...props
15
+ }: React.ComponentProps<typeof SliderPrimitive.Root>) {
16
+ const _values = React.useMemo(
17
+ () =>
18
+ Array.isArray(value)
19
+ ? value
20
+ : Array.isArray(defaultValue)
21
+ ? defaultValue
22
+ : [min, max],
23
+ [value, defaultValue, min, max],
24
+ );
25
+
26
+ return (
27
+ <SliderPrimitive.Root
28
+ data-slot="slider"
29
+ defaultValue={defaultValue}
30
+ value={value}
31
+ min={min}
32
+ max={max}
33
+ className={cn(
34
+ "relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
35
+ className,
36
+ )}
37
+ {...props}
38
+ >
39
+ <SliderPrimitive.Track
40
+ data-slot="slider-track"
41
+ className={cn(
42
+ "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-4 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5",
43
+ )}
44
+ >
45
+ <SliderPrimitive.Range
46
+ data-slot="slider-range"
47
+ className={cn(
48
+ "bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full",
49
+ )}
50
+ />
51
+ </SliderPrimitive.Track>
52
+ {Array.from({ length: _values.length }, (_, index) => (
53
+ <SliderPrimitive.Thumb
54
+ data-slot="slider-thumb"
55
+ key={index}
56
+ className="cursor-pointer border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
57
+ />
58
+ ))}
59
+ </SliderPrimitive.Root>
60
+ );
61
+ }
62
+
63
+ export { Slider };
@@ -0,0 +1,26 @@
1
+
2
+
3
+ import { useTheme } from "next-themes";
4
+ import { Toaster as Sonner } from "sonner";
5
+ import type { ToasterProps } from "sonner";
6
+
7
+ const Toaster = ({ ...props }: ToasterProps) => {
8
+ const { theme = "system" } = useTheme();
9
+
10
+ return (
11
+ <Sonner
12
+ theme={theme as ToasterProps["theme"]}
13
+ className="toaster group"
14
+ style={
15
+ {
16
+ "--normal-bg": "var(--popover)",
17
+ "--normal-text": "var(--popover-foreground)",
18
+ "--normal-border": "var(--border)",
19
+ } as React.CSSProperties
20
+ }
21
+ {...props}
22
+ />
23
+ );
24
+ };
25
+
26
+ export { Toaster };
@@ -0,0 +1,31 @@
1
+
2
+
3
+ import * as React from "react";
4
+ import * as SwitchPrimitive from "@radix-ui/react-switch";
5
+
6
+ import { cn } from "./utils";
7
+
8
+ function Switch({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof SwitchPrimitive.Root>) {
12
+ return (
13
+ <SwitchPrimitive.Root
14
+ data-slot="switch"
15
+ className={cn(
16
+ "peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-switch-background cursor-pointer focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
17
+ className,
18
+ )}
19
+ {...props}
20
+ >
21
+ <SwitchPrimitive.Thumb
22
+ data-slot="switch-thumb"
23
+ className={cn(
24
+ "bg-card dark:data-[state=unchecked]:bg-card-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0",
25
+ )}
26
+ />
27
+ </SwitchPrimitive.Root>
28
+ );
29
+ }
30
+
31
+ export { Switch };
@@ -0,0 +1,116 @@
1
+
2
+
3
+ import * as React from "react";
4
+
5
+ import { cn } from "./utils";
6
+
7
+ function Table({ className, ...props }: React.ComponentProps<"table">) {
8
+ return (
9
+ <div
10
+ data-slot="table-container"
11
+ className="relative w-full overflow-x-auto"
12
+ >
13
+ <table
14
+ data-slot="table"
15
+ className={cn("w-full caption-bottom text-sm", className)}
16
+ {...props}
17
+ />
18
+ </div>
19
+ );
20
+ }
21
+
22
+ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
23
+ return (
24
+ <thead
25
+ data-slot="table-header"
26
+ className={cn("[&_tr]:border-b", className)}
27
+ {...props}
28
+ />
29
+ );
30
+ }
31
+
32
+ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
33
+ return (
34
+ <tbody
35
+ data-slot="table-body"
36
+ className={cn("[&_tr:last-child]:border-0", className)}
37
+ {...props}
38
+ />
39
+ );
40
+ }
41
+
42
+ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
43
+ return (
44
+ <tfoot
45
+ data-slot="table-footer"
46
+ className={cn(
47
+ "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
48
+ className,
49
+ )}
50
+ {...props}
51
+ />
52
+ );
53
+ }
54
+
55
+ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
56
+ return (
57
+ <tr
58
+ data-slot="table-row"
59
+ className={cn(
60
+ "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
61
+ className,
62
+ )}
63
+ {...props}
64
+ />
65
+ );
66
+ }
67
+
68
+ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
69
+ return (
70
+ <th
71
+ data-slot="table-head"
72
+ className={cn(
73
+ "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:*[&>[role=checkbox]]:translate-y-0.5",
74
+ className,
75
+ )}
76
+ {...props}
77
+ />
78
+ );
79
+ }
80
+
81
+ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
82
+ return (
83
+ <td
84
+ data-slot="table-cell"
85
+ className={cn(
86
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:*[&>[role=checkbox]]:translate-y-0.5",
87
+ className,
88
+ )}
89
+ {...props}
90
+ />
91
+ );
92
+ }
93
+
94
+ function TableCaption({
95
+ className,
96
+ ...props
97
+ }: React.ComponentProps<"caption">) {
98
+ return (
99
+ <caption
100
+ data-slot="table-caption"
101
+ className={cn("text-muted-foreground mt-4 text-sm", className)}
102
+ {...props}
103
+ />
104
+ );
105
+ }
106
+
107
+ export {
108
+ Table,
109
+ TableHeader,
110
+ TableBody,
111
+ TableFooter,
112
+ TableHead,
113
+ TableRow,
114
+ TableCell,
115
+ TableCaption,
116
+ };
@@ -0,0 +1,76 @@
1
+
2
+
3
+ import * as React from "react";
4
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
5
+
6
+ import { cn } from "./utils";
7
+
8
+ function Tabs({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof TabsPrimitive.Root>) {
12
+ return (
13
+ <TabsPrimitive.Root
14
+ data-slot="tabs"
15
+ className={cn("flex flex-col gap-2", className)}
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ function TabsList({
22
+ className,
23
+ ...props
24
+ }: React.ComponentProps<typeof TabsPrimitive.List>) {
25
+ return (
26
+ <TabsPrimitive.List
27
+ data-slot="tabs-list"
28
+ className={cn(
29
+ "bg-muted text-muted-foreground gap-2 dark:bg-slate-900 dark:text-slate-400 inline-flex h-10 w-fit items-center justify-center rounded-lg p-0.5 shadow-sm border border-border dark:border-slate-700",
30
+ className,
31
+ )}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ function TabsTrigger({
38
+ className,
39
+ ...props
40
+ }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
41
+ return (
42
+ <TabsPrimitive.Trigger
43
+ data-slot="tabs-trigger"
44
+ className={cn(
45
+ "cursor-pointer inline-flex h-8 flex-1 items-center justify-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium whitespace-nowrap transition-all border border-gray-300 dark:border-slate-600",
46
+ "text-muted-foreground hover:text-foreground hover:bg-muted/50",
47
+ "dark:text-slate-400 dark:hover:text-slate-200 dark:hover:bg-slate-700/50",
48
+ "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
49
+ "dark:data-[state=active]:bg-slate-700/50 dark:data-[state=active]:text-slate-100 dark:data-[state=active]:shadow-lg dark:data-[state=active]:border dark:data-[state=active]:border-slate-600",
50
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
51
+ "disabled:pointer-events-none disabled:opacity-50",
52
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
53
+ className,
54
+ )}
55
+ {...props}
56
+ />
57
+ );
58
+ }
59
+
60
+ function TabsContent({
61
+ className,
62
+ ...props
63
+ }: React.ComponentProps<typeof TabsPrimitive.Content>) {
64
+ return (
65
+ <TabsPrimitive.Content
66
+ data-slot="tabs-content"
67
+ className={cn(
68
+ "flex-1 outline-none ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
69
+ className
70
+ )}
71
+ {...props}
72
+ />
73
+ );
74
+ }
75
+
76
+ export { Tabs, TabsList, TabsTrigger, TabsContent };
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "./utils";
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "resize-none border-input placeholder: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 flex field-sizing-content min-h-16 w-full rounded-md border bg-input-background px-3 py-2 text-base transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
11
+ className,
12
+ )}
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ export { Textarea };
@@ -0,0 +1,89 @@
1
+ import { useThemeStore } from '@/stores/useThemeStore';
2
+ import { Button } from '@/components/ui/button';
3
+ import { Moon, Sun } from 'lucide-react';
4
+ import { cn } from '@/components/ui/utils';
5
+ import { useState, useEffect } from 'react';
6
+
7
+ interface ThemeToggleProps {
8
+ collapsed?: boolean;
9
+ className?: string;
10
+ }
11
+
12
+ export function ThemeToggle({ collapsed = false, className }: ThemeToggleProps) {
13
+ const { theme, toggleTheme } = useThemeStore();
14
+ const [isToggling, setIsToggling] = useState(false);
15
+ const [mounted, setMounted] = useState(false);
16
+
17
+ useEffect(() => {
18
+ setMounted(true);
19
+ }, []);
20
+
21
+ const handleToggle = () => {
22
+ setIsToggling(true);
23
+
24
+ const root = document.documentElement;
25
+ const originalDisplay = root.style.display;
26
+ root.style.display = 'none';
27
+
28
+ toggleTheme();
29
+
30
+ requestAnimationFrame(() => {
31
+ root.style.display = originalDisplay;
32
+ setIsToggling(false);
33
+ });
34
+ };
35
+
36
+ if (!mounted) {
37
+ return (
38
+ <Button
39
+ variant="ghost"
40
+ size={collapsed ? 'icon' : 'default'}
41
+ className={cn(
42
+ "transition-none hover:bg-accent",
43
+ collapsed
44
+ ? "h-10 w-10 p-0"
45
+ : "w-full justify-start gap-3 px-3 py-2 h-auto",
46
+ className
47
+ )}
48
+ disabled
49
+ >
50
+ <div className="relative flex items-center">
51
+ <Sun className="h-4 w-4 shrink-0" />
52
+ </div>
53
+ {!collapsed && (
54
+ <span className="font-medium">Carregando...</span>
55
+ )}
56
+ </Button>
57
+ );
58
+ }
59
+
60
+ return (
61
+ <Button
62
+ variant="ghost"
63
+ size={collapsed ? 'icon' : 'default'}
64
+ className={cn(
65
+ "transition-none hover:bg-accent",
66
+ collapsed
67
+ ? "h-10 w-10 p-0"
68
+ : "w-full justify-start gap-3 px-3 py-2 h-auto",
69
+ className
70
+ )}
71
+ onClick={handleToggle}
72
+ title={theme === 'light' ? 'Alternar para modo escuro' : 'Alternar para modo claro'}
73
+ disabled={isToggling}
74
+ >
75
+ <div className="relative flex items-center">
76
+ {theme === 'light' ? (
77
+ <Moon className="h-4 w-4 shrink-0" />
78
+ ) : (
79
+ <Sun className="h-4 w-4 shrink-0" />
80
+ )}
81
+ </div>
82
+ {!collapsed && (
83
+ <span className="font-medium">
84
+ {theme === 'light' ? 'Modo Escuro' : 'Modo Claro'}
85
+ </span>
86
+ )}
87
+ </Button>
88
+ );
89
+ }
@@ -0,0 +1,73 @@
1
+
2
+
3
+ import * as React from "react";
4
+ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
5
+ import { type VariantProps } from "class-variance-authority";
6
+
7
+ import { cn } from "./utils";
8
+ import { toggleVariants } from "./toggle";
9
+
10
+ const ToggleGroupContext = React.createContext<
11
+ VariantProps<typeof toggleVariants>
12
+ >({
13
+ size: "default",
14
+ variant: "default",
15
+ });
16
+
17
+ function ToggleGroup({
18
+ className,
19
+ variant,
20
+ size,
21
+ children,
22
+ ...props
23
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
24
+ VariantProps<typeof toggleVariants>) {
25
+ return (
26
+ <ToggleGroupPrimitive.Root
27
+ data-slot="toggle-group"
28
+ data-variant={variant}
29
+ data-size={size}
30
+ className={cn(
31
+ "group/toggle-group flex w-fit items-center rounded-md data-[variant=outline]:shadow-xs",
32
+ className,
33
+ )}
34
+ {...props}
35
+ >
36
+ <ToggleGroupContext.Provider value={{ variant, size }}>
37
+ {children}
38
+ </ToggleGroupContext.Provider>
39
+ </ToggleGroupPrimitive.Root>
40
+ );
41
+ }
42
+
43
+ function ToggleGroupItem({
44
+ className,
45
+ children,
46
+ variant,
47
+ size,
48
+ ...props
49
+ }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
50
+ VariantProps<typeof toggleVariants>) {
51
+ const context = React.useContext(ToggleGroupContext);
52
+
53
+ return (
54
+ <ToggleGroupPrimitive.Item
55
+ data-slot="toggle-group-item"
56
+ data-variant={context.variant || variant}
57
+ data-size={context.size || size}
58
+ className={cn(
59
+ toggleVariants({
60
+ variant: context.variant || variant,
61
+ size: context.size || size,
62
+ }),
63
+ "min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l",
64
+ className,
65
+ )}
66
+ {...props}
67
+ >
68
+ {children}
69
+ </ToggleGroupPrimitive.Item>
70
+ );
71
+ }
72
+
73
+ export { ToggleGroup, ToggleGroupItem };
@@ -0,0 +1,47 @@
1
+
2
+
3
+ import * as React from "react";
4
+ import * as TogglePrimitive from "@radix-ui/react-toggle";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+
7
+ import { cn } from "./utils";
8
+
9
+ const toggleVariants = cva(
10
+ "cursor-pointer inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: "bg-transparent",
15
+ outline:
16
+ "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
17
+ },
18
+ size: {
19
+ default: "h-9 px-2 min-w-9",
20
+ sm: "h-8 px-1.5 min-w-8",
21
+ lg: "h-10 px-2.5 min-w-10",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ size: "default",
27
+ },
28
+ },
29
+ );
30
+
31
+ function Toggle({
32
+ className,
33
+ variant,
34
+ size,
35
+ ...props
36
+ }: React.ComponentProps<typeof TogglePrimitive.Root> &
37
+ VariantProps<typeof toggleVariants>) {
38
+ return (
39
+ <TogglePrimitive.Root
40
+ data-slot="toggle"
41
+ className={cn(toggleVariants({ variant, size, className }))}
42
+ {...props}
43
+ />
44
+ );
45
+ }
46
+
47
+ export { Toggle, toggleVariants };