@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.
- package/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/index.cjs +6003 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2310 -0
- package/dist/index.d.ts +2310 -0
- package/dist/index.js +5828 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +96 -0
- package/dist/tailwind-preset.cjs +106 -0
- package/dist/tailwind-preset.cjs.map +1 -0
- package/dist/tailwind-preset.d.cts +23 -0
- package/dist/tailwind-preset.d.ts +23 -0
- package/dist/tailwind-preset.js +101 -0
- package/dist/tailwind-preset.js.map +1 -0
- package/package.json +154 -0
- package/src/components/accordion.tsx +187 -0
- package/src/components/alert-dialog.tsx +143 -0
- package/src/components/autocomplete.tsx +271 -0
- package/src/components/badge.tsx +62 -0
- package/src/components/button.tsx +85 -0
- package/src/components/calendar.tsx +235 -0
- package/src/components/card.tsx +94 -0
- package/src/components/checkbox.tsx +77 -0
- package/src/components/chip.tsx +77 -0
- package/src/components/confirmation-modal.tsx +195 -0
- package/src/components/context-menu.tsx +406 -0
- package/src/components/copy-button.tsx +84 -0
- package/src/components/data-grid/DataGrid.tsx +1027 -0
- package/src/components/data-grid/components/CellEditor.tsx +346 -0
- package/src/components/data-grid/components/FilterPopover.tsx +459 -0
- package/src/components/data-grid/components/HeaderCell.tsx +207 -0
- package/src/components/data-grid/components/index.ts +14 -0
- package/src/components/data-grid/hooks/index.ts +28 -0
- package/src/components/data-grid/hooks/useColumnResize.ts +378 -0
- package/src/components/data-grid/hooks/useDataGridState.ts +346 -0
- package/src/components/data-grid/hooks/useKeyboardNavigation.ts +361 -0
- package/src/components/data-grid/index.ts +71 -0
- package/src/components/data-grid/types.ts +478 -0
- package/src/components/data-grid/utils/dataProcessing.ts +277 -0
- package/src/components/data-grid/utils/index.ts +12 -0
- package/src/components/date-picker.tsx +366 -0
- package/src/components/dropdown-menu.tsx +230 -0
- package/src/components/icon-button.tsx +157 -0
- package/src/components/input.tsx +40 -0
- package/src/components/label.tsx +37 -0
- package/src/components/loading-spinner.tsx +113 -0
- package/src/components/modal.tsx +207 -0
- package/src/components/popover.tsx +62 -0
- package/src/components/progress.tsx +41 -0
- package/src/components/resizable-panel.tsx +434 -0
- package/src/components/resize-handle.tsx +187 -0
- package/src/components/select.tsx +160 -0
- package/src/components/separator.tsx +50 -0
- package/src/components/skeleton.tsx +37 -0
- package/src/components/switch.tsx +59 -0
- package/src/components/table.tsx +136 -0
- package/src/components/tabs.tsx +102 -0
- package/src/components/textarea.tsx +36 -0
- package/src/components/theme-picker.tsx +245 -0
- package/src/components/toaster.tsx +84 -0
- package/src/components/tooltip.tsx +199 -0
- package/src/index.ts +318 -0
- package/src/styles.css +96 -0
- package/src/tailwind-preset.ts +129 -0
- package/src/theme/index.ts +41 -0
- package/src/theme/presets.ts +502 -0
- package/src/theme/types.ts +164 -0
- package/src/theme/utils.ts +309 -0
- 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 };
|