@pylonsync/create-pylon 0.3.343 → 0.3.344

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 (128) hide show
  1. package/package.json +1 -1
  2. package/templates/agency/components/ui/badge.tsx +37 -0
  3. package/templates/agency/components/ui/dialog.tsx +110 -0
  4. package/templates/agency/components/ui/input.tsx +30 -0
  5. package/templates/agency/components/ui/label.tsx +21 -0
  6. package/templates/agency/components/ui/select.tsx +39 -0
  7. package/templates/agency/components/ui/table.tsx +124 -0
  8. package/templates/agency/components/ui/textarea.tsx +24 -0
  9. package/templates/agency/package.json +1 -0
  10. package/templates/ai-chat/components/ui/badge.tsx +37 -0
  11. package/templates/ai-chat/components/ui/button.tsx +56 -0
  12. package/templates/ai-chat/components/ui/card.tsx +90 -0
  13. package/templates/ai-chat/components/ui/dialog.tsx +110 -0
  14. package/templates/ai-chat/components/ui/input.tsx +30 -0
  15. package/templates/ai-chat/components/ui/label.tsx +21 -0
  16. package/templates/ai-chat/components/ui/select.tsx +39 -0
  17. package/templates/ai-chat/components/ui/table.tsx +124 -0
  18. package/templates/ai-chat/components/ui/textarea.tsx +24 -0
  19. package/templates/ai-chat/package.json +1 -0
  20. package/templates/ai-studio/components/ui/badge.tsx +37 -0
  21. package/templates/ai-studio/components/ui/button.tsx +56 -0
  22. package/templates/ai-studio/components/ui/card.tsx +90 -0
  23. package/templates/ai-studio/components/ui/dialog.tsx +110 -0
  24. package/templates/ai-studio/components/ui/input.tsx +30 -0
  25. package/templates/ai-studio/components/ui/label.tsx +21 -0
  26. package/templates/ai-studio/components/ui/select.tsx +39 -0
  27. package/templates/ai-studio/components/ui/table.tsx +124 -0
  28. package/templates/ai-studio/components/ui/textarea.tsx +24 -0
  29. package/templates/ai-studio/package.json +1 -0
  30. package/templates/barebones/components/ui/badge.tsx +37 -0
  31. package/templates/barebones/components/ui/dialog.tsx +110 -0
  32. package/templates/barebones/components/ui/input.tsx +30 -0
  33. package/templates/barebones/components/ui/label.tsx +21 -0
  34. package/templates/barebones/components/ui/select.tsx +39 -0
  35. package/templates/barebones/components/ui/table.tsx +124 -0
  36. package/templates/barebones/components/ui/textarea.tsx +24 -0
  37. package/templates/barebones/package.json +1 -0
  38. package/templates/chat/components/ui/badge.tsx +37 -0
  39. package/templates/chat/components/ui/dialog.tsx +110 -0
  40. package/templates/chat/components/ui/input.tsx +30 -0
  41. package/templates/chat/components/ui/label.tsx +21 -0
  42. package/templates/chat/components/ui/select.tsx +39 -0
  43. package/templates/chat/components/ui/table.tsx +124 -0
  44. package/templates/chat/components/ui/textarea.tsx +24 -0
  45. package/templates/chat/package.json +1 -0
  46. package/templates/consumer/components/ui/badge.tsx +37 -0
  47. package/templates/consumer/components/ui/dialog.tsx +110 -0
  48. package/templates/consumer/components/ui/input.tsx +30 -0
  49. package/templates/consumer/components/ui/label.tsx +21 -0
  50. package/templates/consumer/components/ui/select.tsx +39 -0
  51. package/templates/consumer/components/ui/table.tsx +124 -0
  52. package/templates/consumer/components/ui/textarea.tsx +24 -0
  53. package/templates/consumer/package.json +1 -0
  54. package/templates/creator/components/ui/badge.tsx +37 -0
  55. package/templates/creator/components/ui/dialog.tsx +110 -0
  56. package/templates/creator/components/ui/input.tsx +30 -0
  57. package/templates/creator/components/ui/label.tsx +21 -0
  58. package/templates/creator/components/ui/select.tsx +39 -0
  59. package/templates/creator/components/ui/table.tsx +124 -0
  60. package/templates/creator/components/ui/textarea.tsx +24 -0
  61. package/templates/creator/package.json +1 -0
  62. package/templates/default/components/ui/badge.tsx +37 -0
  63. package/templates/default/components/ui/dialog.tsx +110 -0
  64. package/templates/default/components/ui/input.tsx +30 -0
  65. package/templates/default/components/ui/label.tsx +21 -0
  66. package/templates/default/components/ui/select.tsx +39 -0
  67. package/templates/default/components/ui/table.tsx +124 -0
  68. package/templates/default/components/ui/textarea.tsx +24 -0
  69. package/templates/default/package.json +1 -0
  70. package/templates/directory/components/ui/badge.tsx +37 -0
  71. package/templates/directory/components/ui/dialog.tsx +110 -0
  72. package/templates/directory/components/ui/input.tsx +30 -0
  73. package/templates/directory/components/ui/label.tsx +21 -0
  74. package/templates/directory/components/ui/select.tsx +39 -0
  75. package/templates/directory/components/ui/table.tsx +124 -0
  76. package/templates/directory/components/ui/textarea.tsx +24 -0
  77. package/templates/directory/package.json +1 -0
  78. package/templates/local-service/components/ui/badge.tsx +37 -0
  79. package/templates/local-service/components/ui/dialog.tsx +110 -0
  80. package/templates/local-service/components/ui/input.tsx +30 -0
  81. package/templates/local-service/components/ui/label.tsx +21 -0
  82. package/templates/local-service/components/ui/select.tsx +39 -0
  83. package/templates/local-service/components/ui/table.tsx +124 -0
  84. package/templates/local-service/components/ui/textarea.tsx +24 -0
  85. package/templates/local-service/package.json +1 -0
  86. package/templates/marketplace/components/ui/badge.tsx +37 -0
  87. package/templates/marketplace/components/ui/button.tsx +56 -0
  88. package/templates/marketplace/components/ui/card.tsx +90 -0
  89. package/templates/marketplace/components/ui/dialog.tsx +110 -0
  90. package/templates/marketplace/components/ui/input.tsx +30 -0
  91. package/templates/marketplace/components/ui/label.tsx +21 -0
  92. package/templates/marketplace/components/ui/select.tsx +39 -0
  93. package/templates/marketplace/components/ui/table.tsx +124 -0
  94. package/templates/marketplace/components/ui/textarea.tsx +24 -0
  95. package/templates/marketplace/lib/utils.ts +10 -0
  96. package/templates/marketplace/package.json +1 -0
  97. package/templates/restaurant/components/ui/badge.tsx +37 -0
  98. package/templates/restaurant/components/ui/dialog.tsx +110 -0
  99. package/templates/restaurant/components/ui/input.tsx +30 -0
  100. package/templates/restaurant/components/ui/label.tsx +21 -0
  101. package/templates/restaurant/components/ui/select.tsx +39 -0
  102. package/templates/restaurant/components/ui/table.tsx +124 -0
  103. package/templates/restaurant/components/ui/textarea.tsx +24 -0
  104. package/templates/restaurant/package.json +1 -0
  105. package/templates/shop/components/ui/badge.tsx +37 -0
  106. package/templates/shop/components/ui/dialog.tsx +110 -0
  107. package/templates/shop/components/ui/input.tsx +30 -0
  108. package/templates/shop/components/ui/label.tsx +21 -0
  109. package/templates/shop/components/ui/select.tsx +39 -0
  110. package/templates/shop/components/ui/table.tsx +124 -0
  111. package/templates/shop/components/ui/textarea.tsx +24 -0
  112. package/templates/shop/package.json +1 -0
  113. package/templates/todo/components/ui/badge.tsx +37 -0
  114. package/templates/todo/components/ui/dialog.tsx +110 -0
  115. package/templates/todo/components/ui/input.tsx +30 -0
  116. package/templates/todo/components/ui/label.tsx +21 -0
  117. package/templates/todo/components/ui/select.tsx +39 -0
  118. package/templates/todo/components/ui/table.tsx +124 -0
  119. package/templates/todo/components/ui/textarea.tsx +24 -0
  120. package/templates/todo/package.json +1 -0
  121. package/templates/waitlist/components/ui/badge.tsx +37 -0
  122. package/templates/waitlist/components/ui/dialog.tsx +110 -0
  123. package/templates/waitlist/components/ui/input.tsx +30 -0
  124. package/templates/waitlist/components/ui/label.tsx +21 -0
  125. package/templates/waitlist/components/ui/select.tsx +39 -0
  126. package/templates/waitlist/components/ui/table.tsx +124 -0
  127. package/templates/waitlist/components/ui/textarea.tsx +24 -0
  128. package/templates/waitlist/package.json +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonsync/create-pylon",
3
- "version": "0.3.343",
3
+ "version": "0.3.344",
4
4
  "description": "Scaffold a new Pylon app — realtime backend + web/mobile/expo frontends in one command. Run via `npm create @pylonsync/pylon@latest`.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -0,0 +1,37 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "@/lib/utils";
5
+
6
+ const badgeVariants = cva(
7
+ "inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "border-transparent bg-primary text-primary-foreground",
12
+ secondary: "border-transparent bg-secondary text-secondary-foreground",
13
+ destructive: "border-transparent bg-destructive text-white",
14
+ outline: "text-foreground",
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ variant: "default",
19
+ },
20
+ },
21
+ );
22
+
23
+ export interface BadgeProps
24
+ extends React.HTMLAttributes<HTMLSpanElement>,
25
+ VariantProps<typeof badgeVariants> {}
26
+
27
+ function Badge({ className, variant, ...props }: BadgeProps) {
28
+ return (
29
+ <span
30
+ data-slot="badge"
31
+ className={cn(badgeVariants({ variant }), className)}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ export { Badge, badgeVariants };
@@ -0,0 +1,110 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
5
+ import { X } from "lucide-react";
6
+
7
+ import { cn } from "@/lib/utils";
8
+
9
+ const Dialog = DialogPrimitive.Root;
10
+ const DialogTrigger = DialogPrimitive.Trigger;
11
+ const DialogPortal = DialogPrimitive.Portal;
12
+ const DialogClose = DialogPrimitive.Close;
13
+
14
+ const DialogOverlay = React.forwardRef<
15
+ React.ElementRef<typeof DialogPrimitive.Overlay>,
16
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
17
+ >(({ className, ...props }, ref) => (
18
+ <DialogPrimitive.Overlay
19
+ ref={ref}
20
+ className={cn(
21
+ "fixed inset-0 z-50 bg-black/50 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
+ />
26
+ ));
27
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
28
+
29
+ const DialogContent = React.forwardRef<
30
+ React.ElementRef<typeof DialogPrimitive.Content>,
31
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
32
+ >(({ className, children, ...props }, ref) => (
33
+ <DialogPortal>
34
+ <DialogOverlay />
35
+ <DialogPrimitive.Content
36
+ ref={ref}
37
+ className={cn(
38
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border bg-background p-6 shadow-lg duration-200",
39
+ "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",
40
+ className,
41
+ )}
42
+ {...props}
43
+ >
44
+ {children}
45
+ <DialogPrimitive.Close className="absolute right-3 top-3 rounded-md p-1 text-muted-foreground opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring">
46
+ <X className="size-4" />
47
+ <span className="sr-only">Close</span>
48
+ </DialogPrimitive.Close>
49
+ </DialogPrimitive.Content>
50
+ </DialogPortal>
51
+ ));
52
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
53
+
54
+ function DialogHeader({
55
+ className,
56
+ ...props
57
+ }: React.HTMLAttributes<HTMLDivElement>) {
58
+ return (
59
+ <div className={cn("flex flex-col gap-1.5 text-left", className)} {...props} />
60
+ );
61
+ }
62
+
63
+ function DialogFooter({
64
+ className,
65
+ ...props
66
+ }: React.HTMLAttributes<HTMLDivElement>) {
67
+ return (
68
+ <div
69
+ className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
70
+ {...props}
71
+ />
72
+ );
73
+ }
74
+
75
+ const DialogTitle = React.forwardRef<
76
+ React.ElementRef<typeof DialogPrimitive.Title>,
77
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
78
+ >(({ className, ...props }, ref) => (
79
+ <DialogPrimitive.Title
80
+ ref={ref}
81
+ className={cn("text-base font-semibold leading-none tracking-tight", className)}
82
+ {...props}
83
+ />
84
+ ));
85
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
86
+
87
+ const DialogDescription = React.forwardRef<
88
+ React.ElementRef<typeof DialogPrimitive.Description>,
89
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
90
+ >(({ className, ...props }, ref) => (
91
+ <DialogPrimitive.Description
92
+ ref={ref}
93
+ className={cn("text-sm text-muted-foreground", className)}
94
+ {...props}
95
+ />
96
+ ));
97
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
98
+
99
+ export {
100
+ Dialog,
101
+ DialogClose,
102
+ DialogContent,
103
+ DialogDescription,
104
+ DialogFooter,
105
+ DialogHeader,
106
+ DialogOverlay,
107
+ DialogPortal,
108
+ DialogTitle,
109
+ DialogTrigger,
110
+ };
@@ -0,0 +1,30 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ function Input({
6
+ className,
7
+ type,
8
+ ...props
9
+ }: React.InputHTMLAttributes<HTMLInputElement>) {
10
+ return (
11
+ <input
12
+ type={type}
13
+ data-slot="input"
14
+ className={cn(
15
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors",
16
+ "placeholder:text-muted-foreground",
17
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
18
+ "disabled:cursor-not-allowed disabled:opacity-50",
19
+ // Date/time inputs render a native picker indicator that ignores the
20
+ // text color; nudge it so it stays visible in dark mode.
21
+ "[&::-webkit-calendar-picker-indicator]:opacity-60 dark:[&::-webkit-calendar-picker-indicator]:invert",
22
+ "file:border-0 file:bg-transparent file:text-sm file:font-medium",
23
+ className,
24
+ )}
25
+ {...props}
26
+ />
27
+ );
28
+ }
29
+
30
+ export { Input };
@@ -0,0 +1,21 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ function Label({
6
+ className,
7
+ ...props
8
+ }: React.LabelHTMLAttributes<HTMLLabelElement>) {
9
+ return (
10
+ <label
11
+ data-slot="label"
12
+ className={cn(
13
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
14
+ className,
15
+ )}
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ export { Label };
@@ -0,0 +1,39 @@
1
+ import * as React from "react";
2
+ import { ChevronDown } from "lucide-react";
3
+
4
+ import { cn } from "@/lib/utils";
5
+
6
+ /**
7
+ * A styled native `<select>`.
8
+ *
9
+ * shadcn's Select is a Radix listbox; this deliberately isn't. A native select
10
+ * needs no extra dependency, is keyboard- and screen-reader-correct for free,
11
+ * and opens as the platform picker on mobile — which is what you want for the
12
+ * plain "pick one value" case that scaffolded forms are full of. Reach for
13
+ * `npx shadcn add select` when you need custom option rendering or search.
14
+ */
15
+ function Select({
16
+ className,
17
+ children,
18
+ ...props
19
+ }: React.SelectHTMLAttributes<HTMLSelectElement>) {
20
+ return (
21
+ <div className="relative">
22
+ <select
23
+ data-slot="select"
24
+ className={cn(
25
+ "flex h-9 w-full appearance-none rounded-md border border-input bg-transparent py-1 pl-3 pr-8 text-sm shadow-sm transition-colors",
26
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
27
+ "disabled:cursor-not-allowed disabled:opacity-50",
28
+ className,
29
+ )}
30
+ {...props}
31
+ >
32
+ {children}
33
+ </select>
34
+ <ChevronDown className="pointer-events-none absolute right-2.5 top-1/2 size-4 -translate-y-1/2 opacity-50" />
35
+ </div>
36
+ );
37
+ }
38
+
39
+ export { Select };
@@ -0,0 +1,124 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ // The wrapper owns the horizontal scroll so a wide table never widens the page.
6
+ function Table({ className, ...props }: React.HTMLAttributes<HTMLTableElement>) {
7
+ return (
8
+ <div className="relative w-full overflow-x-auto">
9
+ <table
10
+ data-slot="table"
11
+ className={cn("w-full caption-bottom text-sm", className)}
12
+ {...props}
13
+ />
14
+ </div>
15
+ );
16
+ }
17
+
18
+ function TableHeader({
19
+ className,
20
+ ...props
21
+ }: React.HTMLAttributes<HTMLTableSectionElement>) {
22
+ return (
23
+ <thead
24
+ data-slot="table-header"
25
+ className={cn("[&_tr]:border-b", className)}
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ function TableBody({
32
+ className,
33
+ ...props
34
+ }: React.HTMLAttributes<HTMLTableSectionElement>) {
35
+ return (
36
+ <tbody
37
+ data-slot="table-body"
38
+ className={cn("[&_tr:last-child]:border-0", className)}
39
+ {...props}
40
+ />
41
+ );
42
+ }
43
+
44
+ function TableFooter({
45
+ className,
46
+ ...props
47
+ }: React.HTMLAttributes<HTMLTableSectionElement>) {
48
+ return (
49
+ <tfoot
50
+ data-slot="table-footer"
51
+ className={cn("border-t bg-muted/50 font-medium", className)}
52
+ {...props}
53
+ />
54
+ );
55
+ }
56
+
57
+ function TableRow({
58
+ className,
59
+ ...props
60
+ }: React.HTMLAttributes<HTMLTableRowElement>) {
61
+ return (
62
+ <tr
63
+ data-slot="table-row"
64
+ className={cn(
65
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
66
+ className,
67
+ )}
68
+ {...props}
69
+ />
70
+ );
71
+ }
72
+
73
+ function TableHead({
74
+ className,
75
+ ...props
76
+ }: React.ThHTMLAttributes<HTMLTableCellElement>) {
77
+ return (
78
+ <th
79
+ data-slot="table-head"
80
+ className={cn(
81
+ "h-10 px-3 text-left align-middle text-xs font-medium text-muted-foreground",
82
+ className,
83
+ )}
84
+ {...props}
85
+ />
86
+ );
87
+ }
88
+
89
+ function TableCell({
90
+ className,
91
+ ...props
92
+ }: React.TdHTMLAttributes<HTMLTableCellElement>) {
93
+ return (
94
+ <td
95
+ data-slot="table-cell"
96
+ className={cn("p-3 align-middle", className)}
97
+ {...props}
98
+ />
99
+ );
100
+ }
101
+
102
+ function TableCaption({
103
+ className,
104
+ ...props
105
+ }: React.HTMLAttributes<HTMLTableCaptionElement>) {
106
+ return (
107
+ <caption
108
+ data-slot="table-caption"
109
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
110
+ {...props}
111
+ />
112
+ );
113
+ }
114
+
115
+ export {
116
+ Table,
117
+ TableHeader,
118
+ TableBody,
119
+ TableFooter,
120
+ TableHead,
121
+ TableRow,
122
+ TableCell,
123
+ TableCaption,
124
+ };
@@ -0,0 +1,24 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ function Textarea({
6
+ className,
7
+ ...props
8
+ }: React.TextareaHTMLAttributes<HTMLTextAreaElement>) {
9
+ return (
10
+ <textarea
11
+ data-slot="textarea"
12
+ className={cn(
13
+ "flex min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors",
14
+ "placeholder:text-muted-foreground",
15
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
16
+ "disabled:cursor-not-allowed disabled:opacity-50",
17
+ className,
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ export { Textarea };
@@ -23,6 +23,7 @@
23
23
  "clsx": "^2.1.1",
24
24
  "tailwind-merge": "^2.5.0",
25
25
  "lucide-react": "^0.460.0",
26
+ "@radix-ui/react-dialog": "^1.1.4",
26
27
  "@radix-ui/react-slot": "^1.1.0",
27
28
  "@react-pdf/renderer": "^4.5.1"
28
29
  },
@@ -0,0 +1,37 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "@/lib/utils";
5
+
6
+ const badgeVariants = cva(
7
+ "inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "border-transparent bg-primary text-primary-foreground",
12
+ secondary: "border-transparent bg-secondary text-secondary-foreground",
13
+ destructive: "border-transparent bg-destructive text-white",
14
+ outline: "text-foreground",
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ variant: "default",
19
+ },
20
+ },
21
+ );
22
+
23
+ export interface BadgeProps
24
+ extends React.HTMLAttributes<HTMLSpanElement>,
25
+ VariantProps<typeof badgeVariants> {}
26
+
27
+ function Badge({ className, variant, ...props }: BadgeProps) {
28
+ return (
29
+ <span
30
+ data-slot="badge"
31
+ className={cn(badgeVariants({ variant }), className)}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ export { Badge, badgeVariants };
@@ -0,0 +1,56 @@
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/utils";
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium 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:
14
+ "bg-destructive text-white hover:bg-destructive/90",
15
+ outline:
16
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17
+ secondary:
18
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
19
+ ghost: "hover:bg-accent hover:text-accent-foreground",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ size: {
23
+ default: "h-9 px-4 py-2",
24
+ sm: "h-8 rounded-md px-3 text-xs",
25
+ lg: "h-10 rounded-md px-8",
26
+ icon: "h-9 w-9",
27
+ },
28
+ },
29
+ defaultVariants: {
30
+ variant: "default",
31
+ size: "default",
32
+ },
33
+ },
34
+ );
35
+
36
+ export interface ButtonProps
37
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38
+ VariantProps<typeof buttonVariants> {
39
+ asChild?: boolean;
40
+ }
41
+
42
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
44
+ const Comp = asChild ? Slot : "button";
45
+ return (
46
+ <Comp
47
+ className={cn(buttonVariants({ variant, size, className }))}
48
+ ref={ref}
49
+ {...props}
50
+ />
51
+ );
52
+ },
53
+ );
54
+ Button.displayName = "Button";
55
+
56
+ export { Button, buttonVariants };
@@ -0,0 +1,90 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
6
+ return (
7
+ <div
8
+ data-slot="card"
9
+ className={cn(
10
+ "rounded-xl border bg-card text-card-foreground shadow-sm",
11
+ className,
12
+ )}
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ function CardHeader({
19
+ className,
20
+ ...props
21
+ }: React.HTMLAttributes<HTMLDivElement>) {
22
+ return (
23
+ <div
24
+ data-slot="card-header"
25
+ className={cn("flex flex-col space-y-1.5 p-6", className)}
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ function CardTitle({
32
+ className,
33
+ ...props
34
+ }: React.HTMLAttributes<HTMLDivElement>) {
35
+ return (
36
+ <div
37
+ data-slot="card-title"
38
+ className={cn("font-semibold leading-none tracking-tight", className)}
39
+ {...props}
40
+ />
41
+ );
42
+ }
43
+
44
+ function CardDescription({
45
+ className,
46
+ ...props
47
+ }: React.HTMLAttributes<HTMLDivElement>) {
48
+ return (
49
+ <div
50
+ data-slot="card-description"
51
+ className={cn("text-sm text-muted-foreground", className)}
52
+ {...props}
53
+ />
54
+ );
55
+ }
56
+
57
+ function CardContent({
58
+ className,
59
+ ...props
60
+ }: React.HTMLAttributes<HTMLDivElement>) {
61
+ return (
62
+ <div
63
+ data-slot="card-content"
64
+ className={cn("p-6 pt-0", className)}
65
+ {...props}
66
+ />
67
+ );
68
+ }
69
+
70
+ function CardFooter({
71
+ className,
72
+ ...props
73
+ }: React.HTMLAttributes<HTMLDivElement>) {
74
+ return (
75
+ <div
76
+ data-slot="card-footer"
77
+ className={cn("flex items-center p-6 pt-0", className)}
78
+ {...props}
79
+ />
80
+ );
81
+ }
82
+
83
+ export {
84
+ Card,
85
+ CardHeader,
86
+ CardFooter,
87
+ CardTitle,
88
+ CardDescription,
89
+ CardContent,
90
+ };