@cortexasystem/ui 0.1.0 → 1.0.1

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 (59) hide show
  1. package/dist/index.cjs +1326 -643
  2. package/dist/index.d.cts +171 -13
  3. package/dist/index.d.ts +171 -13
  4. package/dist/index.js +1307 -646
  5. package/package.json +3 -3
  6. package/src/assets/isotipo-cortexa-dark.png +0 -0
  7. package/src/assets/isotipo-cortexa-light.png +0 -0
  8. package/src/components/ai/ai-chat.tsx +597 -0
  9. package/src/components/branding/brand-logo.tsx +77 -0
  10. package/src/components/data-display/icons.tsx +81 -0
  11. package/src/components/data-display/profile-avatar.tsx +154 -0
  12. package/src/components/data-display/typography.tsx +46 -0
  13. package/src/components/feedback/empty-state.tsx +63 -0
  14. package/src/components/feedback/loading-state.tsx +93 -0
  15. package/src/components/feedback/module-skeleton.tsx +76 -0
  16. package/src/components/feedback/notification.tsx +111 -0
  17. package/src/components/feedback/skeleton.tsx +9 -0
  18. package/src/components/feedback/spinner.tsx +18 -0
  19. package/src/components/feedback/status-badge.tsx +44 -0
  20. package/src/components/feedback/sync-status-badge.tsx +54 -0
  21. package/src/components/feedback/sync-status-bar.tsx +92 -0
  22. package/src/components/feedback/toaster.tsx +36 -0
  23. package/src/components/forms/searchable-select.tsx +206 -0
  24. package/src/components/forms/select.tsx +142 -0
  25. package/src/components/layout/app-shell.tsx +44 -0
  26. package/src/components/layout/form-section.tsx +21 -0
  27. package/src/components/layout/page-header.tsx +21 -0
  28. package/src/components/layout/theme-toggle.tsx +33 -0
  29. package/src/components/navigation/breadcrumb.tsx +87 -0
  30. package/src/components/navigation/header-user-menu.tsx +108 -0
  31. package/src/components/navigation/navbar.tsx +30 -0
  32. package/src/components/navigation/page-breadcrumb.tsx +44 -0
  33. package/src/components/navigation/sidebar.tsx +104 -0
  34. package/src/components/navigation/steps.tsx +82 -0
  35. package/src/components/overlays/dialog.tsx +94 -0
  36. package/src/components/overlays/drawer.tsx +85 -0
  37. package/src/components/overlays/dropdown-menu.tsx +179 -0
  38. package/src/components/overlays/sheet.tsx +110 -0
  39. package/src/components/primitives/alert.tsx +43 -0
  40. package/src/components/primitives/avatar.tsx +41 -0
  41. package/src/components/primitives/badge.tsx +26 -0
  42. package/src/components/primitives/button.tsx +49 -0
  43. package/src/components/primitives/card.tsx +97 -0
  44. package/src/components/primitives/checkbox.tsx +52 -0
  45. package/src/components/primitives/input.tsx +23 -0
  46. package/src/components/primitives/label.tsx +18 -0
  47. package/src/components/primitives/radio-group.tsx +57 -0
  48. package/src/components/primitives/separator.tsx +23 -0
  49. package/src/components/primitives/switch.tsx +75 -0
  50. package/src/components/primitives/textarea.tsx +18 -0
  51. package/src/components/tables/data-table.tsx +214 -0
  52. package/src/components/tables/data-table.types.ts +9 -0
  53. package/src/components/tables/table-row-actions.tsx +61 -0
  54. package/src/components/tables/table.tsx +88 -0
  55. package/src/declarations.d.ts +14 -0
  56. package/src/index.ts +50 -0
  57. package/src/lib/cn.ts +6 -0
  58. package/src/providers/theme-provider.tsx +90 -0
  59. package/src/styles.css +1 -1
@@ -0,0 +1,179 @@
1
+ import * as React from "react";
2
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
3
+ import { Check, ChevronRight, Circle } from "lucide-react";
4
+
5
+ import { cn } from "../../lib/cn";
6
+
7
+ const DropdownMenu = DropdownMenuPrimitive.Root;
8
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
9
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group;
10
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
11
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
12
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
13
+
14
+ const DropdownMenuSubTrigger = React.forwardRef<
15
+ React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
16
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
17
+ inset?: boolean;
18
+ }
19
+ >(({ className, inset, children, ...props }, ref) => (
20
+ <DropdownMenuPrimitive.SubTrigger
21
+ ref={ref}
22
+ className={cn(
23
+ "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
24
+ inset && "pl-8",
25
+ className
26
+ )}
27
+ {...props}
28
+ >
29
+ {children}
30
+ <ChevronRight className="ml-auto" />
31
+ </DropdownMenuPrimitive.SubTrigger>
32
+ ));
33
+
34
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
35
+
36
+ const DropdownMenuSubContent = React.forwardRef<
37
+ React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
38
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
39
+ >(({ className, ...props }, ref) => (
40
+ <DropdownMenuPrimitive.SubContent
41
+ ref={ref}
42
+ className={cn(
43
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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 origin-[--radix-dropdown-menu-content-transform-origin]",
44
+ className
45
+ )}
46
+ {...props}
47
+ />
48
+ ));
49
+
50
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
51
+
52
+ const DropdownMenuContent = React.forwardRef<
53
+ React.ElementRef<typeof DropdownMenuPrimitive.Content>,
54
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
55
+ >(({ className, sideOffset = 4, ...props }, ref) => (
56
+ <DropdownMenuPrimitive.Portal>
57
+ <DropdownMenuPrimitive.Content
58
+ ref={ref}
59
+ sideOffset={sideOffset}
60
+ className={cn(
61
+ "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md 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 origin-[--radix-dropdown-menu-content-transform-origin]",
62
+ className
63
+ )}
64
+ {...props}
65
+ />
66
+ </DropdownMenuPrimitive.Portal>
67
+ ));
68
+
69
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
70
+
71
+ const DropdownMenuItem = React.forwardRef<
72
+ React.ElementRef<typeof DropdownMenuPrimitive.Item>,
73
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
74
+ inset?: boolean;
75
+ }
76
+ >(({ className, inset, ...props }, ref) => (
77
+ <DropdownMenuPrimitive.Item
78
+ ref={ref}
79
+ className={cn(
80
+ "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
81
+ inset && "pl-8",
82
+ className
83
+ )}
84
+ {...props}
85
+ />
86
+ ));
87
+
88
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
89
+
90
+ const DropdownMenuCheckboxItem = React.forwardRef<
91
+ React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
92
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
93
+ >(({ className, children, checked, ...props }, ref) => (
94
+ <DropdownMenuPrimitive.CheckboxItem
95
+ ref={ref}
96
+ className={cn(
97
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
98
+ className
99
+ )}
100
+ {...(checked !== undefined ? { checked } : {})}
101
+ {...props}
102
+ >
103
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
104
+ <DropdownMenuPrimitive.ItemIndicator>
105
+ <Check className="h-4 w-4" />
106
+ </DropdownMenuPrimitive.ItemIndicator>
107
+ </span>
108
+ {children}
109
+ </DropdownMenuPrimitive.CheckboxItem>
110
+ ));
111
+
112
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
113
+
114
+ const DropdownMenuRadioItem = React.forwardRef<
115
+ React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
116
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
117
+ >(({ className, children, ...props }, ref) => (
118
+ <DropdownMenuPrimitive.RadioItem
119
+ ref={ref}
120
+ className={cn(
121
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
122
+ className
123
+ )}
124
+ {...props}
125
+ >
126
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
127
+ <DropdownMenuPrimitive.ItemIndicator>
128
+ <Circle className="h-2 w-2 fill-current" />
129
+ </DropdownMenuPrimitive.ItemIndicator>
130
+ </span>
131
+ {children}
132
+ </DropdownMenuPrimitive.RadioItem>
133
+ ));
134
+
135
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
136
+
137
+ const DropdownMenuLabel = React.forwardRef<
138
+ React.ElementRef<typeof DropdownMenuPrimitive.Label>,
139
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
140
+ inset?: boolean;
141
+ }
142
+ >(({ className, inset, ...props }, ref) => (
143
+ <DropdownMenuPrimitive.Label ref={ref} className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)} {...props} />
144
+ ));
145
+
146
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
147
+
148
+ const DropdownMenuSeparator = React.forwardRef<
149
+ React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
150
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
151
+ >(({ className, ...props }, ref) => (
152
+ <DropdownMenuPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
153
+ ));
154
+
155
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
156
+
157
+ const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (
158
+ <span className={cn("ml-auto text-xs tracking-widest opacity-60", className)} {...props} />
159
+ );
160
+
161
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
162
+
163
+ export {
164
+ DropdownMenu,
165
+ DropdownMenuTrigger,
166
+ DropdownMenuContent,
167
+ DropdownMenuItem,
168
+ DropdownMenuCheckboxItem,
169
+ DropdownMenuRadioItem,
170
+ DropdownMenuLabel,
171
+ DropdownMenuSeparator,
172
+ DropdownMenuShortcut,
173
+ DropdownMenuGroup,
174
+ DropdownMenuPortal,
175
+ DropdownMenuSub,
176
+ DropdownMenuSubContent,
177
+ DropdownMenuSubTrigger,
178
+ DropdownMenuRadioGroup
179
+ };
@@ -0,0 +1,110 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as SheetPrimitive from "@radix-ui/react-dialog";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+ import { X } from "lucide-react";
7
+
8
+ import { cn } from "../../lib/cn";
9
+
10
+ const Sheet = SheetPrimitive.Root;
11
+ const SheetTrigger = SheetPrimitive.Trigger;
12
+ const SheetClose = SheetPrimitive.Close;
13
+ const SheetPortal = SheetPrimitive.Portal;
14
+
15
+ const SheetOverlay = React.forwardRef<
16
+ React.ElementRef<typeof SheetPrimitive.Overlay>,
17
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
18
+ >(({ className, ...props }, ref) => (
19
+ <SheetPrimitive.Overlay
20
+ className={cn(
21
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
22
+ className
23
+ )}
24
+ {...props}
25
+ ref={ref}
26
+ />
27
+ ));
28
+
29
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
30
+
31
+ const sheetVariants = cva(
32
+ "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
33
+ {
34
+ variants: {
35
+ side: {
36
+ top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
37
+ bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
38
+ left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
39
+ right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm"
40
+ }
41
+ },
42
+ defaultVariants: {
43
+ side: "right"
44
+ }
45
+ }
46
+ );
47
+
48
+ interface SheetContentProps
49
+ extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
50
+ VariantProps<typeof sheetVariants> {}
51
+
52
+ const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Content>, SheetContentProps>(
53
+ ({ side = "right", className, children, ...props }, ref) => (
54
+ <SheetPortal>
55
+ <SheetOverlay />
56
+ <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
57
+ {children}
58
+ <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
59
+ <X className="h-4 w-4" />
60
+ <span className="sr-only">Close</span>
61
+ </SheetPrimitive.Close>
62
+ </SheetPrimitive.Content>
63
+ </SheetPortal>
64
+ )
65
+ );
66
+
67
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
68
+
69
+ const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
70
+ <div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
71
+ );
72
+
73
+ SheetHeader.displayName = "SheetHeader";
74
+
75
+ const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
76
+ <div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} />
77
+ );
78
+
79
+ SheetFooter.displayName = "SheetFooter";
80
+
81
+ const SheetTitle = React.forwardRef<
82
+ React.ElementRef<typeof SheetPrimitive.Title>,
83
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
84
+ >(({ className, ...props }, ref) => (
85
+ <SheetPrimitive.Title ref={ref} className={cn("text-lg font-semibold text-foreground", className)} {...props} />
86
+ ));
87
+
88
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
89
+
90
+ const SheetDescription = React.forwardRef<
91
+ React.ElementRef<typeof SheetPrimitive.Description>,
92
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
93
+ >(({ className, ...props }, ref) => (
94
+ <SheetPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
95
+ ));
96
+
97
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
98
+
99
+ export {
100
+ Sheet,
101
+ SheetPortal,
102
+ SheetOverlay,
103
+ SheetTrigger,
104
+ SheetClose,
105
+ SheetContent,
106
+ SheetHeader,
107
+ SheetFooter,
108
+ SheetTitle,
109
+ SheetDescription
110
+ };
@@ -0,0 +1,43 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "../../lib/cn";
5
+
6
+ const alertVariants = cva("relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", {
7
+ variants: {
8
+ variant: {
9
+ default: "bg-background text-foreground",
10
+ destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"
11
+ }
12
+ },
13
+ defaultVariants: {
14
+ variant: "default"
15
+ }
16
+ });
17
+
18
+ const Alert = React.forwardRef<
19
+ HTMLDivElement,
20
+ React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
21
+ >(({ className, variant, ...props }, ref) => (
22
+ <div ref={ref} role="alert" className={cn(alertVariants({ variant }), className)} {...props} />
23
+ ));
24
+
25
+ Alert.displayName = "Alert";
26
+
27
+ const AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
28
+ ({ className, ...props }, ref) => (
29
+ <h5 ref={ref} className={cn("mb-1 font-medium leading-none tracking-tight", className)} {...props} />
30
+ )
31
+ );
32
+
33
+ AlertTitle.displayName = "AlertTitle";
34
+
35
+ const AlertDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
36
+ ({ className, ...props }, ref) => (
37
+ <div ref={ref} className={cn("text-sm [&_p]:leading-relaxed", className)} {...props} />
38
+ )
39
+ );
40
+
41
+ AlertDescription.displayName = "AlertDescription";
42
+
43
+ export { Alert, AlertTitle, AlertDescription };
@@ -0,0 +1,41 @@
1
+ import * as React from "react";
2
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
3
+
4
+ import { cn } from "../../lib/cn";
5
+
6
+ const Avatar = React.forwardRef<
7
+ React.ElementRef<typeof AvatarPrimitive.Root>,
8
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
9
+ >(({ className, ...props }, ref) => (
10
+ <AvatarPrimitive.Root
11
+ ref={ref}
12
+ className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
13
+ {...props}
14
+ />
15
+ ));
16
+
17
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
18
+
19
+ const AvatarImage = React.forwardRef<
20
+ React.ElementRef<typeof AvatarPrimitive.Image>,
21
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
22
+ >(({ className, ...props }, ref) => (
23
+ <AvatarPrimitive.Image ref={ref} className={cn("aspect-square h-full w-full", className)} {...props} />
24
+ ));
25
+
26
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
27
+
28
+ const AvatarFallback = React.forwardRef<
29
+ React.ElementRef<typeof AvatarPrimitive.Fallback>,
30
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
31
+ >(({ className, ...props }, ref) => (
32
+ <AvatarPrimitive.Fallback
33
+ ref={ref}
34
+ className={cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className)}
35
+ {...props}
36
+ />
37
+ ));
38
+
39
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
40
+
41
+ export { Avatar, AvatarImage, AvatarFallback };
@@ -0,0 +1,26 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "../../lib/cn";
5
+
6
+ const badgeVariants = cva("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", {
7
+ variants: {
8
+ variant: {
9
+ default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
10
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
11
+ destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
12
+ outline: "text-foreground"
13
+ }
14
+ },
15
+ defaultVariants: {
16
+ variant: "default"
17
+ }
18
+ });
19
+
20
+ export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
21
+
22
+ function Badge({ className, variant, ...props }: BadgeProps) {
23
+ return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
24
+ }
25
+
26
+ export { Badge, badgeVariants };
@@ -0,0 +1,49 @@
1
+ import * as React from "react";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+
5
+ import { cn } from "../../lib/cn";
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
13
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
14
+ outline: "border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground",
15
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
16
+ ghost: "text-foreground shadow-none hover:bg-accent hover:text-accent-foreground",
17
+ link: "h-auto px-0 py-0 text-primary underline-offset-4 shadow-none hover:underline"
18
+ },
19
+ size: {
20
+ default: "h-10 px-4 py-2",
21
+ sm: "h-9 rounded-md px-3",
22
+ lg: "h-11 rounded-md px-8",
23
+ icon: "h-10 w-10"
24
+ }
25
+ },
26
+ defaultVariants: {
27
+ variant: "default",
28
+ size: "default"
29
+ }
30
+ }
31
+ );
32
+
33
+ export interface ButtonProps
34
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
35
+ VariantProps<typeof buttonVariants> {
36
+ asChild?: boolean;
37
+ }
38
+
39
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
40
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
41
+ const Comp = asChild ? Slot : "button";
42
+
43
+ return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;
44
+ }
45
+ );
46
+
47
+ Button.displayName = "Button";
48
+
49
+ export { Button, buttonVariants };
@@ -0,0 +1,97 @@
1
+ import * as React from "react";
2
+ import { type LucideIcon } from "lucide-react";
3
+
4
+ import { cn } from "../../lib/cn";
5
+
6
+ const cardBaseClassName = "rounded-lg border bg-card text-card-foreground shadow-sm";
7
+
8
+ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (
9
+ <div ref={ref} className={cn(cardBaseClassName, className)} {...props} />
10
+ ));
11
+
12
+ Card.displayName = "Card";
13
+
14
+ const ClickableCard = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttributes<HTMLButtonElement>>(
15
+ ({ className, type = "button", ...props }, ref) => (
16
+ <button
17
+ ref={ref}
18
+ type={type}
19
+ className={cn(
20
+ cardBaseClassName,
21
+ "w-full cursor-pointer text-left transition-all hover:bg-accent/30 hover:border-[var(--color-accent-blue)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
22
+ className
23
+ )}
24
+ {...props}
25
+ />
26
+ )
27
+ );
28
+
29
+ ClickableCard.displayName = "ClickableCard";
30
+
31
+ interface CenteredIconCardProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
32
+ icon: LucideIcon;
33
+ title: string;
34
+ iconClassName?: string;
35
+ }
36
+
37
+ const CenteredIconCard = React.forwardRef<HTMLButtonElement, CenteredIconCardProps>(
38
+ ({ className, type = "button", icon: Icon, title, iconClassName, ...props }, ref) => (
39
+ <button
40
+ ref={ref}
41
+ type={type}
42
+ className={cn(
43
+ cardBaseClassName,
44
+ "flex w-full cursor-pointer flex-col items-center justify-center gap-4 p-6 text-center transition-all hover:bg-accent/30 hover:border-[var(--color-accent-blue)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
45
+ className
46
+ )}
47
+ {...props}
48
+ >
49
+ <span className="flex h-12 w-12 items-center justify-center rounded-xl bg-[var(--color-brand)]/10 text-[var(--color-brand)]">
50
+ <Icon className={cn("h-6 w-6", iconClassName)} />
51
+ </span>
52
+ <span className="text-sm font-semibold text-foreground">{title}</span>
53
+ </button>
54
+ )
55
+ );
56
+
57
+ CenteredIconCard.displayName = "CenteredIconCard";
58
+
59
+ const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
60
+ ({ className, ...props }, ref) => (
61
+ <div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
62
+ )
63
+ );
64
+
65
+ CardHeader.displayName = "CardHeader";
66
+
67
+ const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
68
+ ({ className, ...props }, ref) => (
69
+ <div ref={ref} className={cn("text-2xl font-semibold leading-none tracking-tight", className)} {...props} />
70
+ )
71
+ );
72
+
73
+ CardTitle.displayName = "CardTitle";
74
+
75
+ const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
76
+ ({ className, ...props }, ref) => (
77
+ <div ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
78
+ )
79
+ );
80
+
81
+ CardDescription.displayName = "CardDescription";
82
+
83
+ const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
84
+ ({ className, ...props }, ref) => <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
85
+ );
86
+
87
+ CardContent.displayName = "CardContent";
88
+
89
+ const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
90
+ ({ className, ...props }, ref) => (
91
+ <div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />
92
+ )
93
+ );
94
+
95
+ CardFooter.displayName = "CardFooter";
96
+
97
+ export { Card, ClickableCard, CenteredIconCard, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
@@ -0,0 +1,52 @@
1
+ import * as React from "react";
2
+ import { Check } from "lucide-react";
3
+
4
+ import { cn } from "../../lib/cn";
5
+
6
+ type CheckboxProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "type">;
7
+
8
+ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(({ className, ...props }, ref) => (
9
+ <span className="relative inline-flex h-4 w-4 shrink-0">
10
+ <input
11
+ ref={ref}
12
+ type="checkbox"
13
+ className={cn(
14
+ "peer absolute inset-0 h-4 w-4 cursor-pointer appearance-none rounded-[4px] border border-input bg-background shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 checked:border-primary checked:bg-primary",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ <Check
20
+ aria-hidden="true"
21
+ className="pointer-events-none absolute left-1/2 top-1/2 h-3 w-3 -translate-x-1/2 -translate-y-1/2 text-primary-foreground opacity-0 transition-opacity peer-checked:opacity-100"
22
+ />
23
+ </span>
24
+ ));
25
+
26
+ Checkbox.displayName = "Checkbox";
27
+
28
+ interface CheckboxFieldProps extends CheckboxProps {
29
+ label: React.ReactNode;
30
+ description?: React.ReactNode;
31
+ containerClassName?: string;
32
+ }
33
+
34
+ function CheckboxField({ id, label, description, containerClassName, className, ...props }: CheckboxFieldProps) {
35
+ const generatedId = React.useId();
36
+ const inputId = id ?? generatedId;
37
+
38
+ return (
39
+ <label
40
+ htmlFor={inputId}
41
+ className={cn("flex items-center gap-3 rounded-lg border border-border bg-card p-3 transition-colors hover:bg-accent/30", containerClassName)}
42
+ >
43
+ <Checkbox id={inputId} className={className} {...props} />
44
+ <span className="grid gap-1">
45
+ <span className="text-sm font-medium text-foreground">{label}</span>
46
+ {description ? <span className="text-xs text-muted-foreground">{description}</span> : null}
47
+ </span>
48
+ </label>
49
+ );
50
+ }
51
+
52
+ export { Checkbox, CheckboxField };
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "../../lib/cn";
4
+
5
+ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
6
+ ({ className, type, ...props }, ref) => {
7
+ return (
8
+ <input
9
+ type={type}
10
+ className={cn(
11
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
+ className
13
+ )}
14
+ ref={ref}
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+ );
20
+
21
+ Input.displayName = "Input";
22
+
23
+ export { Input };
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+ import * as LabelPrimitive from "@radix-ui/react-label";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+
5
+ import { cn } from "../../lib/cn";
6
+
7
+ const labelVariants = cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
8
+
9
+ const Label = React.forwardRef<
10
+ React.ElementRef<typeof LabelPrimitive.Root>,
11
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>
12
+ >(({ className, ...props }, ref) => (
13
+ <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
14
+ ));
15
+
16
+ Label.displayName = LabelPrimitive.Root.displayName;
17
+
18
+ export { Label };