@optilogic/core 1.0.0-beta.0

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +107 -0
  3. package/dist/index.cjs +6003 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +2310 -0
  6. package/dist/index.d.ts +2310 -0
  7. package/dist/index.js +5828 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/styles.css +96 -0
  10. package/dist/tailwind-preset.cjs +106 -0
  11. package/dist/tailwind-preset.cjs.map +1 -0
  12. package/dist/tailwind-preset.d.cts +23 -0
  13. package/dist/tailwind-preset.d.ts +23 -0
  14. package/dist/tailwind-preset.js +101 -0
  15. package/dist/tailwind-preset.js.map +1 -0
  16. package/package.json +154 -0
  17. package/src/components/accordion.tsx +187 -0
  18. package/src/components/alert-dialog.tsx +143 -0
  19. package/src/components/autocomplete.tsx +271 -0
  20. package/src/components/badge.tsx +62 -0
  21. package/src/components/button.tsx +85 -0
  22. package/src/components/calendar.tsx +235 -0
  23. package/src/components/card.tsx +94 -0
  24. package/src/components/checkbox.tsx +77 -0
  25. package/src/components/chip.tsx +77 -0
  26. package/src/components/confirmation-modal.tsx +195 -0
  27. package/src/components/context-menu.tsx +406 -0
  28. package/src/components/copy-button.tsx +84 -0
  29. package/src/components/data-grid/DataGrid.tsx +1027 -0
  30. package/src/components/data-grid/components/CellEditor.tsx +346 -0
  31. package/src/components/data-grid/components/FilterPopover.tsx +459 -0
  32. package/src/components/data-grid/components/HeaderCell.tsx +207 -0
  33. package/src/components/data-grid/components/index.ts +14 -0
  34. package/src/components/data-grid/hooks/index.ts +28 -0
  35. package/src/components/data-grid/hooks/useColumnResize.ts +378 -0
  36. package/src/components/data-grid/hooks/useDataGridState.ts +346 -0
  37. package/src/components/data-grid/hooks/useKeyboardNavigation.ts +361 -0
  38. package/src/components/data-grid/index.ts +71 -0
  39. package/src/components/data-grid/types.ts +478 -0
  40. package/src/components/data-grid/utils/dataProcessing.ts +277 -0
  41. package/src/components/data-grid/utils/index.ts +12 -0
  42. package/src/components/date-picker.tsx +366 -0
  43. package/src/components/dropdown-menu.tsx +230 -0
  44. package/src/components/icon-button.tsx +157 -0
  45. package/src/components/input.tsx +40 -0
  46. package/src/components/label.tsx +37 -0
  47. package/src/components/loading-spinner.tsx +113 -0
  48. package/src/components/modal.tsx +207 -0
  49. package/src/components/popover.tsx +62 -0
  50. package/src/components/progress.tsx +41 -0
  51. package/src/components/resizable-panel.tsx +434 -0
  52. package/src/components/resize-handle.tsx +187 -0
  53. package/src/components/select.tsx +160 -0
  54. package/src/components/separator.tsx +50 -0
  55. package/src/components/skeleton.tsx +37 -0
  56. package/src/components/switch.tsx +59 -0
  57. package/src/components/table.tsx +136 -0
  58. package/src/components/tabs.tsx +102 -0
  59. package/src/components/textarea.tsx +36 -0
  60. package/src/components/theme-picker.tsx +245 -0
  61. package/src/components/toaster.tsx +84 -0
  62. package/src/components/tooltip.tsx +199 -0
  63. package/src/index.ts +318 -0
  64. package/src/styles.css +96 -0
  65. package/src/tailwind-preset.ts +129 -0
  66. package/src/theme/index.ts +41 -0
  67. package/src/theme/presets.ts +502 -0
  68. package/src/theme/types.ts +164 -0
  69. package/src/theme/utils.ts +309 -0
  70. package/src/utils/cn.ts +14 -0
@@ -0,0 +1,160 @@
1
+ import * as React from "react";
2
+ import * as SelectPrimitive from "@radix-ui/react-select";
3
+ import { Check, ChevronDown, ChevronUp } from "lucide-react";
4
+
5
+ import { cn } from "../utils/cn";
6
+
7
+ const Select = SelectPrimitive.Root;
8
+
9
+ const SelectGroup = SelectPrimitive.Group;
10
+
11
+ const SelectValue = SelectPrimitive.Value;
12
+
13
+ export interface SelectTriggerProps
14
+ extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> {}
15
+
16
+ const SelectTrigger = React.forwardRef<
17
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
18
+ SelectTriggerProps
19
+ >(({ className, children, ...props }, ref) => (
20
+ <SelectPrimitive.Trigger
21
+ ref={ref}
22
+ className={cn(
23
+ "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
24
+ className
25
+ )}
26
+ {...props}
27
+ >
28
+ {children}
29
+ <SelectPrimitive.Icon asChild>
30
+ <ChevronDown className="h-4 w-4 opacity-50" />
31
+ </SelectPrimitive.Icon>
32
+ </SelectPrimitive.Trigger>
33
+ ));
34
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
35
+
36
+ const SelectScrollUpButton = React.forwardRef<
37
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
38
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
39
+ >(({ className, ...props }, ref) => (
40
+ <SelectPrimitive.ScrollUpButton
41
+ ref={ref}
42
+ className={cn(
43
+ "flex cursor-default items-center justify-center py-1",
44
+ className
45
+ )}
46
+ {...props}
47
+ >
48
+ <ChevronUp className="h-4 w-4" />
49
+ </SelectPrimitive.ScrollUpButton>
50
+ ));
51
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
52
+
53
+ const SelectScrollDownButton = React.forwardRef<
54
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
55
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
56
+ >(({ className, ...props }, ref) => (
57
+ <SelectPrimitive.ScrollDownButton
58
+ ref={ref}
59
+ className={cn(
60
+ "flex cursor-default items-center justify-center py-1",
61
+ className
62
+ )}
63
+ {...props}
64
+ >
65
+ <ChevronDown className="h-4 w-4" />
66
+ </SelectPrimitive.ScrollDownButton>
67
+ ));
68
+ SelectScrollDownButton.displayName =
69
+ SelectPrimitive.ScrollDownButton.displayName;
70
+
71
+ const SelectContent = React.forwardRef<
72
+ React.ElementRef<typeof SelectPrimitive.Content>,
73
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
74
+ >(({ className, children, position = "popper", ...props }, ref) => (
75
+ <SelectPrimitive.Portal>
76
+ <SelectPrimitive.Content
77
+ ref={ref}
78
+ className={cn(
79
+ "relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover 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-select-content-transform-origin]",
80
+ position === "popper" &&
81
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
82
+ className
83
+ )}
84
+ position={position}
85
+ {...props}
86
+ >
87
+ <SelectScrollUpButton />
88
+ <SelectPrimitive.Viewport
89
+ className={cn(
90
+ "p-1",
91
+ position === "popper" &&
92
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
93
+ )}
94
+ >
95
+ {children}
96
+ </SelectPrimitive.Viewport>
97
+ <SelectScrollDownButton />
98
+ </SelectPrimitive.Content>
99
+ </SelectPrimitive.Portal>
100
+ ));
101
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
102
+
103
+ const SelectLabel = React.forwardRef<
104
+ React.ElementRef<typeof SelectPrimitive.Label>,
105
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
106
+ >(({ className, ...props }, ref) => (
107
+ <SelectPrimitive.Label
108
+ ref={ref}
109
+ className={cn("px-2 py-1.5 text-sm font-semibold", className)}
110
+ {...props}
111
+ />
112
+ ));
113
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
114
+
115
+ const SelectItem = React.forwardRef<
116
+ React.ElementRef<typeof SelectPrimitive.Item>,
117
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
118
+ >(({ className, children, ...props }, ref) => (
119
+ <SelectPrimitive.Item
120
+ ref={ref}
121
+ className={cn(
122
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
123
+ className
124
+ )}
125
+ {...props}
126
+ >
127
+ <span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
128
+ <SelectPrimitive.ItemIndicator>
129
+ <Check className="h-4 w-4" />
130
+ </SelectPrimitive.ItemIndicator>
131
+ </span>
132
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
133
+ </SelectPrimitive.Item>
134
+ ));
135
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
136
+
137
+ const SelectSeparator = React.forwardRef<
138
+ React.ElementRef<typeof SelectPrimitive.Separator>,
139
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
140
+ >(({ className, ...props }, ref) => (
141
+ <SelectPrimitive.Separator
142
+ ref={ref}
143
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
144
+ {...props}
145
+ />
146
+ ));
147
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
148
+
149
+ export {
150
+ Select,
151
+ SelectGroup,
152
+ SelectValue,
153
+ SelectTrigger,
154
+ SelectContent,
155
+ SelectLabel,
156
+ SelectItem,
157
+ SelectSeparator,
158
+ SelectScrollUpButton,
159
+ SelectScrollDownButton,
160
+ };
@@ -0,0 +1,50 @@
1
+ import * as React from "react";
2
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
3
+
4
+ import { cn } from "../utils/cn";
5
+
6
+ export interface SeparatorProps
7
+ extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> {}
8
+
9
+ /**
10
+ * Separator Component
11
+ *
12
+ * A visual divider between content sections.
13
+ * Can be horizontal (default) or vertical.
14
+ *
15
+ * @example
16
+ * <div>Content above</div>
17
+ * <Separator />
18
+ * <div>Content below</div>
19
+ *
20
+ * @example
21
+ * <div className="flex items-center gap-4">
22
+ * <span>Left</span>
23
+ * <Separator orientation="vertical" className="h-4" />
24
+ * <span>Right</span>
25
+ * </div>
26
+ */
27
+ const Separator = React.forwardRef<
28
+ React.ElementRef<typeof SeparatorPrimitive.Root>,
29
+ SeparatorProps
30
+ >(
31
+ (
32
+ { className, orientation = "horizontal", decorative = true, ...props },
33
+ ref
34
+ ) => (
35
+ <SeparatorPrimitive.Root
36
+ ref={ref}
37
+ decorative={decorative}
38
+ orientation={orientation}
39
+ className={cn(
40
+ "shrink-0 bg-border",
41
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ )
47
+ );
48
+ Separator.displayName = SeparatorPrimitive.Root.displayName;
49
+
50
+ export { Separator };
@@ -0,0 +1,37 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "../utils/cn";
4
+
5
+ export interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {}
6
+
7
+ /**
8
+ * Skeleton Component
9
+ *
10
+ * A loading placeholder with shimmer animation.
11
+ * Use to indicate content that is loading.
12
+ *
13
+ * @example
14
+ * // Text placeholder
15
+ * <Skeleton className="h-4 w-[250px]" />
16
+ *
17
+ * @example
18
+ * // Avatar placeholder
19
+ * <Skeleton className="h-12 w-12 rounded-full" />
20
+ *
21
+ * @example
22
+ * // Card placeholder
23
+ * <div className="space-y-2">
24
+ * <Skeleton className="h-4 w-[250px]" />
25
+ * <Skeleton className="h-4 w-[200px]" />
26
+ * </div>
27
+ */
28
+ function Skeleton({ className, ...props }: SkeletonProps) {
29
+ return (
30
+ <div
31
+ className={cn("animate-pulse rounded-md bg-primary/10", className)}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ export { Skeleton };
@@ -0,0 +1,59 @@
1
+ import * as React from "react";
2
+ import * as SwitchPrimitive from "@radix-ui/react-switch";
3
+
4
+ import { cn } from "../utils/cn";
5
+
6
+ export interface SwitchProps
7
+ extends React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> {}
8
+
9
+ /**
10
+ * Switch Component
11
+ *
12
+ * A toggle switch for boolean on/off states.
13
+ * Accessible alternative to checkbox for settings.
14
+ *
15
+ * @example
16
+ * <Switch id="notifications" />
17
+ * <Label htmlFor="notifications">Enable notifications</Label>
18
+ *
19
+ * @example
20
+ * <Switch checked={isEnabled} onCheckedChange={setIsEnabled} />
21
+ */
22
+ const Switch = React.forwardRef<
23
+ React.ElementRef<typeof SwitchPrimitive.Root>,
24
+ SwitchProps
25
+ >(({ className, ...props }, ref) => (
26
+ <SwitchPrimitive.Root
27
+ className={cn(
28
+ // Base styles
29
+ "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center",
30
+ "rounded-full border-2 border-transparent",
31
+ "transition-colors",
32
+ // Focus styles
33
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
34
+ // Disabled styles
35
+ "disabled:cursor-not-allowed disabled:opacity-50",
36
+ // Unchecked state
37
+ "bg-input",
38
+ // Checked state
39
+ "data-[state=checked]:bg-primary",
40
+ className
41
+ )}
42
+ {...props}
43
+ ref={ref}
44
+ >
45
+ <SwitchPrimitive.Thumb
46
+ className={cn(
47
+ // Base styles
48
+ "pointer-events-none block h-4 w-4 rounded-full",
49
+ "bg-background shadow-lg ring-0",
50
+ "transition-transform",
51
+ // Position based on state
52
+ "data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
53
+ )}
54
+ />
55
+ </SwitchPrimitive.Root>
56
+ ));
57
+ Switch.displayName = SwitchPrimitive.Root.displayName;
58
+
59
+ export { Switch };
@@ -0,0 +1,136 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "../utils/cn";
4
+
5
+ export interface TableProps extends React.HTMLAttributes<HTMLTableElement> {}
6
+
7
+ const Table = React.forwardRef<HTMLTableElement, TableProps>(
8
+ ({ className, ...props }, ref) => (
9
+ <div className="relative w-full overflow-auto">
10
+ <table
11
+ ref={ref}
12
+ className={cn("w-full caption-bottom text-sm", className)}
13
+ {...props}
14
+ />
15
+ </div>
16
+ )
17
+ );
18
+ Table.displayName = "Table";
19
+
20
+ export interface TableHeaderProps
21
+ extends React.HTMLAttributes<HTMLTableSectionElement> {}
22
+
23
+ const TableHeader = React.forwardRef<HTMLTableSectionElement, TableHeaderProps>(
24
+ ({ className, ...props }, ref) => (
25
+ <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
26
+ )
27
+ );
28
+ TableHeader.displayName = "TableHeader";
29
+
30
+ export interface TableBodyProps
31
+ extends React.HTMLAttributes<HTMLTableSectionElement> {}
32
+
33
+ const TableBody = React.forwardRef<HTMLTableSectionElement, TableBodyProps>(
34
+ ({ className, ...props }, ref) => (
35
+ <tbody
36
+ ref={ref}
37
+ className={cn("[&_tr:last-child]:border-0", className)}
38
+ {...props}
39
+ />
40
+ )
41
+ );
42
+ TableBody.displayName = "TableBody";
43
+
44
+ export interface TableFooterProps
45
+ extends React.HTMLAttributes<HTMLTableSectionElement> {}
46
+
47
+ const TableFooter = React.forwardRef<HTMLTableSectionElement, TableFooterProps>(
48
+ ({ className, ...props }, ref) => (
49
+ <tfoot
50
+ ref={ref}
51
+ className={cn(
52
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
53
+ className
54
+ )}
55
+ {...props}
56
+ />
57
+ )
58
+ );
59
+ TableFooter.displayName = "TableFooter";
60
+
61
+ export interface TableRowProps
62
+ extends React.HTMLAttributes<HTMLTableRowElement> {}
63
+
64
+ const TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>(
65
+ ({ className, ...props }, ref) => (
66
+ <tr
67
+ ref={ref}
68
+ className={cn(
69
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
70
+ className
71
+ )}
72
+ {...props}
73
+ />
74
+ )
75
+ );
76
+ TableRow.displayName = "TableRow";
77
+
78
+ export interface TableHeadProps
79
+ extends React.ThHTMLAttributes<HTMLTableCellElement> {}
80
+
81
+ const TableHead = React.forwardRef<HTMLTableCellElement, TableHeadProps>(
82
+ ({ className, ...props }, ref) => (
83
+ <th
84
+ ref={ref}
85
+ className={cn(
86
+ "h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
87
+ className
88
+ )}
89
+ {...props}
90
+ />
91
+ )
92
+ );
93
+ TableHead.displayName = "TableHead";
94
+
95
+ export interface TableCellProps
96
+ extends React.TdHTMLAttributes<HTMLTableCellElement> {}
97
+
98
+ const TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps>(
99
+ ({ className, ...props }, ref) => (
100
+ <td
101
+ ref={ref}
102
+ className={cn(
103
+ "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
104
+ className
105
+ )}
106
+ {...props}
107
+ />
108
+ )
109
+ );
110
+ TableCell.displayName = "TableCell";
111
+
112
+ export interface TableCaptionProps
113
+ extends React.HTMLAttributes<HTMLTableCaptionElement> {}
114
+
115
+ const TableCaption = React.forwardRef<
116
+ HTMLTableCaptionElement,
117
+ TableCaptionProps
118
+ >(({ className, ...props }, ref) => (
119
+ <caption
120
+ ref={ref}
121
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
122
+ {...props}
123
+ />
124
+ ));
125
+ TableCaption.displayName = "TableCaption";
126
+
127
+ export {
128
+ Table,
129
+ TableHeader,
130
+ TableBody,
131
+ TableFooter,
132
+ TableHead,
133
+ TableRow,
134
+ TableCell,
135
+ TableCaption,
136
+ };
@@ -0,0 +1,102 @@
1
+ import * as React from "react";
2
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
3
+
4
+ import { cn } from "../utils/cn";
5
+
6
+ /**
7
+ * Tabs Root
8
+ *
9
+ * Container for tabbed content. Controls which tab is active.
10
+ *
11
+ * @example
12
+ * <Tabs defaultValue="tab1">
13
+ * <TabsList>
14
+ * <TabsTrigger value="tab1">Tab 1</TabsTrigger>
15
+ * <TabsTrigger value="tab2">Tab 2</TabsTrigger>
16
+ * </TabsList>
17
+ * <TabsContent value="tab1">Content 1</TabsContent>
18
+ * <TabsContent value="tab2">Content 2</TabsContent>
19
+ * </Tabs>
20
+ */
21
+ const Tabs = TabsPrimitive.Root;
22
+
23
+ /**
24
+ * TabsList
25
+ *
26
+ * Container for tab triggers. Provides the tab header bar.
27
+ */
28
+ const TabsList = React.forwardRef<
29
+ React.ElementRef<typeof TabsPrimitive.List>,
30
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
31
+ >(({ className, ...props }, ref) => (
32
+ <TabsPrimitive.List
33
+ ref={ref}
34
+ className={cn(
35
+ "inline-flex h-10 items-center justify-start",
36
+ "border-b border-border",
37
+ "bg-transparent",
38
+ className
39
+ )}
40
+ {...props}
41
+ />
42
+ ));
43
+ TabsList.displayName = TabsPrimitive.List.displayName;
44
+
45
+ /**
46
+ * TabsTrigger
47
+ *
48
+ * Individual tab button that activates its associated content.
49
+ */
50
+ const TabsTrigger = React.forwardRef<
51
+ React.ElementRef<typeof TabsPrimitive.Trigger>,
52
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
53
+ >(({ className, ...props }, ref) => (
54
+ <TabsPrimitive.Trigger
55
+ ref={ref}
56
+ className={cn(
57
+ // Base styles
58
+ "inline-flex items-center justify-center whitespace-nowrap",
59
+ "px-4 py-2.5 text-sm font-medium",
60
+ "transition-colors",
61
+ // Border-bottom indicator style
62
+ "border-b-2 -mb-px",
63
+ // Default state
64
+ "border-transparent text-muted-foreground",
65
+ // Hover state
66
+ "hover:text-foreground hover:border-muted-foreground/50",
67
+ // Active/selected state
68
+ "data-[state=active]:border-foreground data-[state=active]:text-foreground",
69
+ // Focus styles
70
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
71
+ // Disabled styles
72
+ "disabled:pointer-events-none disabled:opacity-50",
73
+ className
74
+ )}
75
+ {...props}
76
+ />
77
+ ));
78
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
79
+
80
+ /**
81
+ * TabsContent
82
+ *
83
+ * Container for the content associated with a tab.
84
+ */
85
+ const TabsContent = React.forwardRef<
86
+ React.ElementRef<typeof TabsPrimitive.Content>,
87
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
88
+ >(({ className, ...props }, ref) => (
89
+ <TabsPrimitive.Content
90
+ ref={ref}
91
+ className={cn(
92
+ "mt-2",
93
+ // Focus styles
94
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
95
+ className
96
+ )}
97
+ {...props}
98
+ />
99
+ ));
100
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
101
+
102
+ export { Tabs, TabsList, TabsTrigger, TabsContent };
@@ -0,0 +1,36 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "../utils/cn";
4
+
5
+ export interface TextareaProps
6
+ extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
7
+
8
+ /**
9
+ * Textarea Component
10
+ *
11
+ * A styled multi-line text input with consistent theming.
12
+ * Supports all native textarea attributes.
13
+ *
14
+ * @example
15
+ * <Textarea placeholder="Enter description..." />
16
+ *
17
+ * @example
18
+ * <Textarea rows={5} placeholder="Write your message..." />
19
+ */
20
+ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
21
+ ({ className, ...props }, ref) => {
22
+ return (
23
+ <textarea
24
+ className={cn(
25
+ "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
26
+ className
27
+ )}
28
+ ref={ref}
29
+ {...props}
30
+ />
31
+ );
32
+ }
33
+ );
34
+ Textarea.displayName = "Textarea";
35
+
36
+ export { Textarea };