create-davepi-ui 0.1.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 +29 -0
- package/bin/index.js +229 -0
- package/bin/sync-templates.js +100 -0
- package/package.json +40 -0
- package/templates/default/.env.example +1 -0
- package/templates/default/index.html +13 -0
- package/templates/default/package.json +49 -0
- package/templates/default/postcss.config.cjs +6 -0
- package/templates/default/src/App.tsx +42 -0
- package/templates/default/src/components/AppShell.tsx +23 -0
- package/templates/default/src/components/BulkActionBar.tsx +47 -0
- package/templates/default/src/components/RelatedCreateModal.tsx +91 -0
- package/templates/default/src/components/RelatedList.tsx +70 -0
- package/templates/default/src/components/ResourceForm.tsx +311 -0
- package/templates/default/src/components/ResourceTable.tsx +475 -0
- package/templates/default/src/components/RowActions.tsx +54 -0
- package/templates/default/src/components/Sidebar.tsx +171 -0
- package/templates/default/src/components/ui/button.tsx +43 -0
- package/templates/default/src/components/ui/card.tsx +47 -0
- package/templates/default/src/components/ui/checkbox.tsx +24 -0
- package/templates/default/src/components/ui/command.tsx +117 -0
- package/templates/default/src/components/ui/dialog.tsx +95 -0
- package/templates/default/src/components/ui/dropdown-menu.tsx +78 -0
- package/templates/default/src/components/ui/input.tsx +18 -0
- package/templates/default/src/components/ui/label.tsx +17 -0
- package/templates/default/src/components/ui/popover.tsx +27 -0
- package/templates/default/src/components/ui/select.tsx +83 -0
- package/templates/default/src/components/ui/switch.tsx +21 -0
- package/templates/default/src/components/ui/table.tsx +66 -0
- package/templates/default/src/components/ui/tabs.tsx +53 -0
- package/templates/default/src/components/ui/textarea.tsx +17 -0
- package/templates/default/src/davepi-ui.config.ts +14 -0
- package/templates/default/src/index.css +55 -0
- package/templates/default/src/lib/utils.ts +10 -0
- package/templates/default/src/main.tsx +34 -0
- package/templates/default/src/pages/DashboardPage.tsx +42 -0
- package/templates/default/src/pages/LoginScreen.tsx +77 -0
- package/templates/default/src/pages/ResourceCreatePage.tsx +58 -0
- package/templates/default/src/pages/ResourceDetailPage.tsx +171 -0
- package/templates/default/src/pages/ResourceEditPage.tsx +52 -0
- package/templates/default/src/pages/ResourceListPage.tsx +8 -0
- package/templates/default/src/resourceOverrides.ts +34 -0
- package/templates/default/src/resources/account.ts +25 -0
- package/templates/default/src/resources/category.ts +7 -0
- package/templates/default/src/resources/contact.ts +40 -0
- package/templates/default/src/resources/product.ts +7 -0
- package/templates/default/src/resources/project.ts +7 -0
- package/templates/default/src/resources/quote.ts +12 -0
- package/templates/default/src/vite-env.d.ts +9 -0
- package/templates/default/src/widgets/CurrencyInput.tsx +44 -0
- package/templates/default/src/widgets/DateInput.tsx +36 -0
- package/templates/default/src/widgets/EmailInput.tsx +28 -0
- package/templates/default/src/widgets/EnumSelect.tsx +35 -0
- package/templates/default/src/widgets/FileUploaderStub.tsx +9 -0
- package/templates/default/src/widgets/JsonEditor.tsx +64 -0
- package/templates/default/src/widgets/NumberInput.tsx +36 -0
- package/templates/default/src/widgets/RelationPicker.tsx +349 -0
- package/templates/default/src/widgets/SwitchWidget.tsx +20 -0
- package/templates/default/src/widgets/TagInput.tsx +83 -0
- package/templates/default/src/widgets/TextAreaWidget.tsx +27 -0
- package/templates/default/src/widgets/TextInput.tsx +32 -0
- package/templates/default/src/widgets/UrlInput.tsx +27 -0
- package/templates/default/src/widgets/registry.ts +51 -0
- package/templates/default/src/widgets/types.ts +26 -0
- package/templates/default/tailwind.config.ts +54 -0
- package/templates/default/tsconfig.json +40 -0
- package/templates/default/vite.config.ts +16 -0
- package/templates/pinned-versions.json +5 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { forwardRef, type ButtonHTMLAttributes } from 'react';
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
const buttonVariants = cva(
|
|
7
|
+
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium 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',
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
12
|
+
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
13
|
+
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
|
14
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
15
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
16
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
default: 'h-10 px-4 py-2',
|
|
20
|
+
sm: 'h-9 rounded-md px-3',
|
|
21
|
+
lg: 'h-11 rounded-md px-8',
|
|
22
|
+
icon: 'h-10 w-10',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: { variant: 'default', size: 'default' },
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export interface ButtonProps
|
|
30
|
+
extends ButtonHTMLAttributes<HTMLButtonElement>,
|
|
31
|
+
VariantProps<typeof buttonVariants> {
|
|
32
|
+
asChild?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
|
|
36
|
+
{ className, variant, size, asChild = false, ...props },
|
|
37
|
+
ref
|
|
38
|
+
) {
|
|
39
|
+
const Comp = asChild ? Slot : 'button';
|
|
40
|
+
return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export { buttonVariants };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { forwardRef, type HTMLAttributes } from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
export const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
|
|
5
|
+
function Card({ className, ...props }, ref) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
ref={ref}
|
|
9
|
+
className={cn(
|
|
10
|
+
'rounded-lg border bg-card text-card-foreground shadow-sm',
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export const CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
|
|
20
|
+
function CardHeader({ className, ...props }, ref) {
|
|
21
|
+
return <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />;
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export const CardTitle = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
|
|
26
|
+
function CardTitle({ className, ...props }, ref) {
|
|
27
|
+
return (
|
|
28
|
+
<h3
|
|
29
|
+
ref={ref}
|
|
30
|
+
className={cn('text-lg font-semibold leading-none tracking-tight', className)}
|
|
31
|
+
{...(props as HTMLAttributes<HTMLHeadingElement>)}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
export const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
|
|
38
|
+
function CardContent({ className, ...props }, ref) {
|
|
39
|
+
return <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />;
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
export const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
|
|
44
|
+
function CardFooter({ className, ...props }, ref) {
|
|
45
|
+
return <div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />;
|
|
46
|
+
}
|
|
47
|
+
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from 'react';
|
|
2
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
3
|
+
import { Check } from 'lucide-react';
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
export const Checkbox = forwardRef<
|
|
7
|
+
ElementRef<typeof CheckboxPrimitive.Root>,
|
|
8
|
+
ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
|
9
|
+
>(function Checkbox({ className, ...props }, ref) {
|
|
10
|
+
return (
|
|
11
|
+
<CheckboxPrimitive.Root
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn(
|
|
14
|
+
'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
>
|
|
19
|
+
<CheckboxPrimitive.Indicator className="flex items-center justify-center text-current">
|
|
20
|
+
<Check className="h-4 w-4" />
|
|
21
|
+
</CheckboxPrimitive.Indicator>
|
|
22
|
+
</CheckboxPrimitive.Root>
|
|
23
|
+
);
|
|
24
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from 'react';
|
|
2
|
+
import { Command as CommandPrimitive } from 'cmdk';
|
|
3
|
+
import { Search } from 'lucide-react';
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
export const Command = forwardRef<
|
|
7
|
+
ElementRef<typeof CommandPrimitive>,
|
|
8
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive>
|
|
9
|
+
>(function Command({ className, ...props }, ref) {
|
|
10
|
+
return (
|
|
11
|
+
<CommandPrimitive
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn(
|
|
14
|
+
'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const CommandInput = forwardRef<
|
|
23
|
+
ElementRef<typeof CommandPrimitive.Input>,
|
|
24
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
|
25
|
+
>(function CommandInput({ className, ...props }, ref) {
|
|
26
|
+
return (
|
|
27
|
+
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
|
28
|
+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
29
|
+
<CommandPrimitive.Input
|
|
30
|
+
ref={ref}
|
|
31
|
+
className={cn(
|
|
32
|
+
'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const CommandList = forwardRef<
|
|
42
|
+
ElementRef<typeof CommandPrimitive.List>,
|
|
43
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
|
44
|
+
>(function CommandList({ className, ...props }, ref) {
|
|
45
|
+
return (
|
|
46
|
+
<CommandPrimitive.List
|
|
47
|
+
ref={ref}
|
|
48
|
+
className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export const CommandEmpty = forwardRef<
|
|
55
|
+
ElementRef<typeof CommandPrimitive.Empty>,
|
|
56
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
|
57
|
+
>(function CommandEmpty(props, ref) {
|
|
58
|
+
return <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export const CommandGroup = forwardRef<
|
|
62
|
+
ElementRef<typeof CommandPrimitive.Group>,
|
|
63
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
|
64
|
+
>(function CommandGroup({ className, ...props }, ref) {
|
|
65
|
+
return (
|
|
66
|
+
<CommandPrimitive.Group
|
|
67
|
+
ref={ref}
|
|
68
|
+
className={cn(
|
|
69
|
+
'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export const CommandSeparator = forwardRef<
|
|
78
|
+
ElementRef<typeof CommandPrimitive.Separator>,
|
|
79
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
|
80
|
+
>(function CommandSeparator({ className, ...props }, ref) {
|
|
81
|
+
return (
|
|
82
|
+
<CommandPrimitive.Separator
|
|
83
|
+
ref={ref}
|
|
84
|
+
className={cn('-mx-1 h-px bg-border', className)}
|
|
85
|
+
{...props}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export const CommandItem = forwardRef<
|
|
91
|
+
ElementRef<typeof CommandPrimitive.Item>,
|
|
92
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
|
93
|
+
>(function CommandItem({ className, ...props }, ref) {
|
|
94
|
+
return (
|
|
95
|
+
<CommandPrimitive.Item
|
|
96
|
+
ref={ref}
|
|
97
|
+
className={cn(
|
|
98
|
+
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50",
|
|
99
|
+
className
|
|
100
|
+
)}
|
|
101
|
+
{...props}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export const CommandLoading = forwardRef<
|
|
107
|
+
ElementRef<typeof CommandPrimitive.Loading>,
|
|
108
|
+
ComponentPropsWithoutRef<typeof CommandPrimitive.Loading>
|
|
109
|
+
>(function CommandLoading(props, ref) {
|
|
110
|
+
return (
|
|
111
|
+
<CommandPrimitive.Loading
|
|
112
|
+
ref={ref}
|
|
113
|
+
className="py-6 text-center text-sm text-muted-foreground"
|
|
114
|
+
{...props}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
type ComponentPropsWithoutRef,
|
|
4
|
+
type ElementRef,
|
|
5
|
+
type HTMLAttributes,
|
|
6
|
+
} from 'react';
|
|
7
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
8
|
+
import { X } from 'lucide-react';
|
|
9
|
+
import { cn } from '@/lib/utils';
|
|
10
|
+
|
|
11
|
+
export const Dialog = DialogPrimitive.Root;
|
|
12
|
+
export const DialogTrigger = DialogPrimitive.Trigger;
|
|
13
|
+
export const DialogPortal = DialogPrimitive.Portal;
|
|
14
|
+
export const DialogClose = DialogPrimitive.Close;
|
|
15
|
+
|
|
16
|
+
const DialogOverlay = forwardRef<
|
|
17
|
+
ElementRef<typeof DialogPrimitive.Overlay>,
|
|
18
|
+
ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
19
|
+
>(function DialogOverlay({ className, ...props }, ref) {
|
|
20
|
+
return (
|
|
21
|
+
<DialogPrimitive.Overlay
|
|
22
|
+
ref={ref}
|
|
23
|
+
className={cn(
|
|
24
|
+
'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',
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const DialogContent = forwardRef<
|
|
33
|
+
ElementRef<typeof DialogPrimitive.Content>,
|
|
34
|
+
ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
|
35
|
+
>(function DialogContent({ className, children, ...props }, ref) {
|
|
36
|
+
return (
|
|
37
|
+
<DialogPortal>
|
|
38
|
+
<DialogOverlay />
|
|
39
|
+
<DialogPrimitive.Content
|
|
40
|
+
ref={ref}
|
|
41
|
+
className={cn(
|
|
42
|
+
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg sm:rounded-lg',
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
{children}
|
|
48
|
+
<DialogPrimitive.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">
|
|
49
|
+
<X className="h-4 w-4" />
|
|
50
|
+
<span className="sr-only">Close</span>
|
|
51
|
+
</DialogPrimitive.Close>
|
|
52
|
+
</DialogPrimitive.Content>
|
|
53
|
+
</DialogPortal>
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const DialogHeader = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (
|
|
58
|
+
<div
|
|
59
|
+
className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
export const DialogFooter = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (
|
|
65
|
+
<div
|
|
66
|
+
className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
export const DialogTitle = forwardRef<
|
|
72
|
+
ElementRef<typeof DialogPrimitive.Title>,
|
|
73
|
+
ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
74
|
+
>(function DialogTitle({ className, ...props }, ref) {
|
|
75
|
+
return (
|
|
76
|
+
<DialogPrimitive.Title
|
|
77
|
+
ref={ref}
|
|
78
|
+
className={cn('text-lg font-semibold leading-none tracking-tight', className)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const DialogDescription = forwardRef<
|
|
85
|
+
ElementRef<typeof DialogPrimitive.Description>,
|
|
86
|
+
ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
87
|
+
>(function DialogDescription({ className, ...props }, ref) {
|
|
88
|
+
return (
|
|
89
|
+
<DialogPrimitive.Description
|
|
90
|
+
ref={ref}
|
|
91
|
+
className={cn('text-sm text-muted-foreground', className)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from 'react';
|
|
2
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
3
|
+
import { Check, ChevronRight } from 'lucide-react';
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
export const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
7
|
+
export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
8
|
+
export const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
9
|
+
export const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
10
|
+
|
|
11
|
+
export const DropdownMenuContent = forwardRef<
|
|
12
|
+
ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
13
|
+
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
14
|
+
>(function DropdownMenuContent({ className, sideOffset = 4, ...props }, ref) {
|
|
15
|
+
return (
|
|
16
|
+
<DropdownMenuPrimitive.Portal>
|
|
17
|
+
<DropdownMenuPrimitive.Content
|
|
18
|
+
ref={ref}
|
|
19
|
+
sideOffset={sideOffset}
|
|
20
|
+
className={cn(
|
|
21
|
+
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
/>
|
|
26
|
+
</DropdownMenuPrimitive.Portal>
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export const DropdownMenuItem = forwardRef<
|
|
31
|
+
ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
32
|
+
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & { inset?: boolean }
|
|
33
|
+
>(function DropdownMenuItem({ className, inset, ...props }, ref) {
|
|
34
|
+
return (
|
|
35
|
+
<DropdownMenuPrimitive.Item
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={cn(
|
|
38
|
+
'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',
|
|
39
|
+
inset && 'pl-8',
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export const DropdownMenuSeparator = forwardRef<
|
|
48
|
+
ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
49
|
+
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
50
|
+
>(function DropdownMenuSeparator({ className, ...props }, ref) {
|
|
51
|
+
return (
|
|
52
|
+
<DropdownMenuPrimitive.Separator
|
|
53
|
+
ref={ref}
|
|
54
|
+
className={cn('-mx-1 my-1 h-px bg-muted', className)}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const DropdownMenuLabel = forwardRef<
|
|
61
|
+
ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
62
|
+
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }
|
|
63
|
+
>(function DropdownMenuLabel({ className, inset, ...props }, ref) {
|
|
64
|
+
return (
|
|
65
|
+
<DropdownMenuPrimitive.Label
|
|
66
|
+
ref={ref}
|
|
67
|
+
className={cn(
|
|
68
|
+
'px-2 py-1.5 text-xs font-medium text-muted-foreground',
|
|
69
|
+
inset && 'pl-8',
|
|
70
|
+
className
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Re-export icons used by consumers building menus.
|
|
78
|
+
export { Check, ChevronRight };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { forwardRef, type InputHTMLAttributes } from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
export const Input = forwardRef<HTMLInputElement, InputHTMLAttributes<HTMLInputElement>>(
|
|
5
|
+
function Input({ className, type, ...props }, ref) {
|
|
6
|
+
return (
|
|
7
|
+
<input
|
|
8
|
+
ref={ref}
|
|
9
|
+
type={type}
|
|
10
|
+
className={cn(
|
|
11
|
+
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background 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',
|
|
12
|
+
className
|
|
13
|
+
)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { forwardRef, type LabelHTMLAttributes } from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
export const Label = forwardRef<HTMLLabelElement, LabelHTMLAttributes<HTMLLabelElement>>(
|
|
5
|
+
function Label({ className, ...props }, ref) {
|
|
6
|
+
return (
|
|
7
|
+
<label
|
|
8
|
+
ref={ref}
|
|
9
|
+
className={cn(
|
|
10
|
+
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from 'react';
|
|
2
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
|
|
5
|
+
export const Popover = PopoverPrimitive.Root;
|
|
6
|
+
export const PopoverTrigger = PopoverPrimitive.Trigger;
|
|
7
|
+
export const PopoverAnchor = PopoverPrimitive.Anchor;
|
|
8
|
+
|
|
9
|
+
export const PopoverContent = forwardRef<
|
|
10
|
+
ElementRef<typeof PopoverPrimitive.Content>,
|
|
11
|
+
ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
|
12
|
+
>(function PopoverContent({ className, align = 'start', sideOffset = 4, ...props }, ref) {
|
|
13
|
+
return (
|
|
14
|
+
<PopoverPrimitive.Portal>
|
|
15
|
+
<PopoverPrimitive.Content
|
|
16
|
+
ref={ref}
|
|
17
|
+
align={align}
|
|
18
|
+
sideOffset={sideOffset}
|
|
19
|
+
className={cn(
|
|
20
|
+
'z-50 w-72 rounded-md border bg-popover p-1 text-popover-foreground shadow-md outline-none',
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
</PopoverPrimitive.Portal>
|
|
26
|
+
);
|
|
27
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from 'react';
|
|
2
|
+
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
3
|
+
import { Check, ChevronDown } from 'lucide-react';
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
export const Select = SelectPrimitive.Root;
|
|
7
|
+
export const SelectGroup = SelectPrimitive.Group;
|
|
8
|
+
export const SelectValue = SelectPrimitive.Value;
|
|
9
|
+
|
|
10
|
+
export const SelectTrigger = forwardRef<
|
|
11
|
+
ElementRef<typeof SelectPrimitive.Trigger>,
|
|
12
|
+
ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
13
|
+
>(function SelectTrigger({ className, children, ...props }, ref) {
|
|
14
|
+
return (
|
|
15
|
+
<SelectPrimitive.Trigger
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(
|
|
18
|
+
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
<SelectPrimitive.Icon asChild>
|
|
25
|
+
<ChevronDown className="h-4 w-4 opacity-50" />
|
|
26
|
+
</SelectPrimitive.Icon>
|
|
27
|
+
</SelectPrimitive.Trigger>
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const SelectContent = forwardRef<
|
|
32
|
+
ElementRef<typeof SelectPrimitive.Content>,
|
|
33
|
+
ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
34
|
+
>(function SelectContent({ className, children, position = 'popper', ...props }, ref) {
|
|
35
|
+
return (
|
|
36
|
+
<SelectPrimitive.Portal>
|
|
37
|
+
<SelectPrimitive.Content
|
|
38
|
+
ref={ref}
|
|
39
|
+
className={cn(
|
|
40
|
+
'relative z-50 max-h-96 min-w-[8rem] overflow-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',
|
|
41
|
+
position === 'popper' &&
|
|
42
|
+
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
position={position}
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
<SelectPrimitive.Viewport
|
|
49
|
+
className={cn(
|
|
50
|
+
'p-1',
|
|
51
|
+
position === 'popper' &&
|
|
52
|
+
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
{children}
|
|
56
|
+
</SelectPrimitive.Viewport>
|
|
57
|
+
</SelectPrimitive.Content>
|
|
58
|
+
</SelectPrimitive.Portal>
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const SelectItem = forwardRef<
|
|
63
|
+
ElementRef<typeof SelectPrimitive.Item>,
|
|
64
|
+
ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
65
|
+
>(function SelectItem({ className, children, ...props }, ref) {
|
|
66
|
+
return (
|
|
67
|
+
<SelectPrimitive.Item
|
|
68
|
+
ref={ref}
|
|
69
|
+
className={cn(
|
|
70
|
+
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
71
|
+
className
|
|
72
|
+
)}
|
|
73
|
+
{...props}
|
|
74
|
+
>
|
|
75
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
76
|
+
<SelectPrimitive.ItemIndicator>
|
|
77
|
+
<Check className="h-4 w-4" />
|
|
78
|
+
</SelectPrimitive.ItemIndicator>
|
|
79
|
+
</span>
|
|
80
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
81
|
+
</SelectPrimitive.Item>
|
|
82
|
+
);
|
|
83
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from 'react';
|
|
2
|
+
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
|
|
5
|
+
export const Switch = forwardRef<
|
|
6
|
+
ElementRef<typeof SwitchPrimitives.Root>,
|
|
7
|
+
ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
|
8
|
+
>(function Switch({ className, ...props }, ref) {
|
|
9
|
+
return (
|
|
10
|
+
<SwitchPrimitives.Root
|
|
11
|
+
ref={ref}
|
|
12
|
+
className={cn(
|
|
13
|
+
'peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
|
14
|
+
className
|
|
15
|
+
)}
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
<SwitchPrimitives.Thumb className="pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0" />
|
|
19
|
+
</SwitchPrimitives.Root>
|
|
20
|
+
);
|
|
21
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { forwardRef, type HTMLAttributes, type TdHTMLAttributes, type ThHTMLAttributes } from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
export const Table = forwardRef<HTMLTableElement, HTMLAttributes<HTMLTableElement>>(
|
|
5
|
+
function Table({ className, ...props }, ref) {
|
|
6
|
+
return (
|
|
7
|
+
<div className="relative w-full overflow-auto">
|
|
8
|
+
<table ref={ref} className={cn('w-full caption-bottom text-sm', className)} {...props} />
|
|
9
|
+
</div>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const TableHeader = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(
|
|
15
|
+
function TableHeader({ className, ...props }, ref) {
|
|
16
|
+
return <thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />;
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const TableBody = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(
|
|
21
|
+
function TableBody({ className, ...props }, ref) {
|
|
22
|
+
return <tbody ref={ref} className={cn('[&_tr:last-child]:border-0', className)} {...props} />;
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export const TableRow = forwardRef<HTMLTableRowElement, HTMLAttributes<HTMLTableRowElement>>(
|
|
27
|
+
function TableRow({ className, ...props }, ref) {
|
|
28
|
+
return (
|
|
29
|
+
<tr
|
|
30
|
+
ref={ref}
|
|
31
|
+
className={cn(
|
|
32
|
+
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export const TableHead = forwardRef<HTMLTableCellElement, ThHTMLAttributes<HTMLTableCellElement>>(
|
|
42
|
+
function TableHead({ className, ...props }, ref) {
|
|
43
|
+
return (
|
|
44
|
+
<th
|
|
45
|
+
ref={ref}
|
|
46
|
+
className={cn(
|
|
47
|
+
'h-10 px-3 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
|
48
|
+
className
|
|
49
|
+
)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export const TableCell = forwardRef<HTMLTableCellElement, TdHTMLAttributes<HTMLTableCellElement>>(
|
|
57
|
+
function TableCell({ className, ...props }, ref) {
|
|
58
|
+
return (
|
|
59
|
+
<td
|
|
60
|
+
ref={ref}
|
|
61
|
+
className={cn('p-3 align-middle [&:has([role=checkbox])]:pr-0', className)}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
);
|