ucode-agent 1.3.0 → 1.5.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 (56) hide show
  1. package/README.md +42 -12
  2. package/package.json +5 -3
  3. package/skills/build-app/SKILL.md +23 -3
  4. package/skills/ui-ux/SKILL.md +5 -1
  5. package/src/core/loop.js +181 -20
  6. package/src/core/provider.js +40 -12
  7. package/src/core/updater.js +95 -0
  8. package/src/tools/browser.js +258 -0
  9. package/src/tools/index.js +51 -1
  10. package/src/tools/scaffold.js +130 -0
  11. package/src/tools/shell.js +8 -1
  12. package/src/ui/screen.js +20 -6
  13. package/templates/next-shadcn/AGENTS.md +9 -0
  14. package/templates/next-shadcn/README.md +9 -0
  15. package/templates/next-shadcn/TEMPLATE.md +39 -0
  16. package/templates/next-shadcn/_gitignore +41 -0
  17. package/templates/next-shadcn/_package-lock.json +10278 -0
  18. package/templates/next-shadcn/components.json +25 -0
  19. package/templates/next-shadcn/eslint.config.mjs +18 -0
  20. package/templates/next-shadcn/next-env.d.ts +5 -0
  21. package/templates/next-shadcn/next.config.ts +7 -0
  22. package/templates/next-shadcn/package.json +37 -0
  23. package/templates/next-shadcn/postcss.config.mjs +7 -0
  24. package/templates/next-shadcn/src/app/favicon.ico +0 -0
  25. package/templates/next-shadcn/src/app/globals.css +155 -0
  26. package/templates/next-shadcn/src/app/layout.tsx +42 -0
  27. package/templates/next-shadcn/src/app/page.tsx +14 -0
  28. package/templates/next-shadcn/src/components/theme-provider.tsx +7 -0
  29. package/templates/next-shadcn/src/components/theme-toggle.tsx +27 -0
  30. package/templates/next-shadcn/src/components/ui/alert-dialog.tsx +187 -0
  31. package/templates/next-shadcn/src/components/ui/avatar.tsx +108 -0
  32. package/templates/next-shadcn/src/components/ui/badge.tsx +51 -0
  33. package/templates/next-shadcn/src/components/ui/button.tsx +57 -0
  34. package/templates/next-shadcn/src/components/ui/calendar.tsx +221 -0
  35. package/templates/next-shadcn/src/components/ui/card.tsx +102 -0
  36. package/templates/next-shadcn/src/components/ui/checkbox.tsx +28 -0
  37. package/templates/next-shadcn/src/components/ui/command.tsx +196 -0
  38. package/templates/next-shadcn/src/components/ui/dialog.tsx +160 -0
  39. package/templates/next-shadcn/src/components/ui/dropdown-menu.tsx +267 -0
  40. package/templates/next-shadcn/src/components/ui/input-group.tsx +158 -0
  41. package/templates/next-shadcn/src/components/ui/input.tsx +19 -0
  42. package/templates/next-shadcn/src/components/ui/label.tsx +19 -0
  43. package/templates/next-shadcn/src/components/ui/popover.tsx +89 -0
  44. package/templates/next-shadcn/src/components/ui/progress.tsx +82 -0
  45. package/templates/next-shadcn/src/components/ui/scroll-area.tsx +54 -0
  46. package/templates/next-shadcn/src/components/ui/select.tsx +200 -0
  47. package/templates/next-shadcn/src/components/ui/separator.tsx +24 -0
  48. package/templates/next-shadcn/src/components/ui/sheet.tsx +138 -0
  49. package/templates/next-shadcn/src/components/ui/skeleton.tsx +13 -0
  50. package/templates/next-shadcn/src/components/ui/sonner.tsx +49 -0
  51. package/templates/next-shadcn/src/components/ui/switch.tsx +31 -0
  52. package/templates/next-shadcn/src/components/ui/tabs.tsx +81 -0
  53. package/templates/next-shadcn/src/components/ui/textarea.tsx +17 -0
  54. package/templates/next-shadcn/src/components/ui/tooltip.tsx +65 -0
  55. package/templates/next-shadcn/src/lib/utils.ts +1 -0
  56. package/templates/next-shadcn/tsconfig.json +34 -0
@@ -0,0 +1,51 @@
1
+ import { mergeProps } from "@base-ui/react/merge-props"
2
+ import { useRender } from "@base-ui/react/use-render"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+ import { cn } from "cn"
5
+
6
+ const badgeVariants = cva(
7
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
12
+ secondary:
13
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
14
+ destructive:
15
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
16
+ outline:
17
+ "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
18
+ ghost:
19
+ "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: "default",
25
+ },
26
+ }
27
+ )
28
+
29
+ function Badge({
30
+ className,
31
+ variant = "default",
32
+ render,
33
+ ...props
34
+ }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
35
+ return useRender({
36
+ defaultTagName: "span",
37
+ props: mergeProps<"span">(
38
+ {
39
+ className: cn(badgeVariants({ variant }), className),
40
+ },
41
+ props
42
+ ),
43
+ render,
44
+ state: {
45
+ slot: "badge",
46
+ variant,
47
+ },
48
+ })
49
+ }
50
+
51
+ export { Badge, badgeVariants }
@@ -0,0 +1,57 @@
1
+ import { Button as ButtonPrimitive } from "@base-ui/react/button"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { cn } from "cn"
4
+
5
+ const buttonVariants = cva(
6
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
11
+ outline:
12
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
15
+ ghost:
16
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
17
+ destructive:
18
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
19
+ link: "text-primary underline-offset-4 hover:underline",
20
+ },
21
+ size: {
22
+ default:
23
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
24
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
25
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
26
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
27
+ icon: "size-8",
28
+ "icon-xs":
29
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
30
+ "icon-sm":
31
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
32
+ "icon-lg": "size-9",
33
+ },
34
+ },
35
+ defaultVariants: {
36
+ variant: "default",
37
+ size: "default",
38
+ },
39
+ }
40
+ )
41
+
42
+ function Button({
43
+ className,
44
+ variant = "default",
45
+ size = "default",
46
+ ...props
47
+ }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
48
+ return (
49
+ <ButtonPrimitive
50
+ data-slot="button"
51
+ className={cn(buttonVariants({ variant, size, className }))}
52
+ {...props}
53
+ />
54
+ )
55
+ }
56
+
57
+ export { Button, buttonVariants }
@@ -0,0 +1,221 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "cn"
5
+ import {
6
+ DayPicker,
7
+ getDefaultClassNames,
8
+ type DayButton,
9
+ type Locale,
10
+ } from "react-day-picker"
11
+
12
+ import { Button, buttonVariants } from "@/components/ui/button"
13
+ import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from "lucide-react"
14
+
15
+ function Calendar({
16
+ className,
17
+ classNames,
18
+ showOutsideDays = true,
19
+ captionLayout = "label",
20
+ buttonVariant = "ghost",
21
+ locale,
22
+ formatters,
23
+ components,
24
+ ...props
25
+ }: React.ComponentProps<typeof DayPicker> & {
26
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"]
27
+ }) {
28
+ const defaultClassNames = getDefaultClassNames()
29
+
30
+ return (
31
+ <DayPicker
32
+ showOutsideDays={showOutsideDays}
33
+ className={cn(
34
+ "group/calendar bg-background p-2 [--cell-radius:var(--radius-md)] [--cell-size:--spacing(7)] in-data-[slot=card-content]:bg-transparent in-data-[slot=popover-content]:bg-transparent",
35
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
36
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
37
+ className
38
+ )}
39
+ captionLayout={captionLayout}
40
+ locale={locale}
41
+ formatters={{
42
+ formatMonthDropdown: (date) =>
43
+ date.toLocaleString(locale?.code, { month: "short" }),
44
+ ...formatters,
45
+ }}
46
+ classNames={{
47
+ root: cn("w-fit", defaultClassNames.root),
48
+ months: cn(
49
+ "relative flex flex-col gap-4 md:flex-row",
50
+ defaultClassNames.months
51
+ ),
52
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
53
+ nav: cn(
54
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
55
+ defaultClassNames.nav
56
+ ),
57
+ button_previous: cn(
58
+ buttonVariants({ variant: buttonVariant }),
59
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
60
+ defaultClassNames.button_previous
61
+ ),
62
+ button_next: cn(
63
+ buttonVariants({ variant: buttonVariant }),
64
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
65
+ defaultClassNames.button_next
66
+ ),
67
+ month_caption: cn(
68
+ "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
69
+ defaultClassNames.month_caption
70
+ ),
71
+ dropdowns: cn(
72
+ "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
73
+ defaultClassNames.dropdowns
74
+ ),
75
+ dropdown_root: cn(
76
+ "relative rounded-(--cell-radius)",
77
+ defaultClassNames.dropdown_root
78
+ ),
79
+ dropdown: cn(
80
+ "absolute inset-0 bg-popover opacity-0",
81
+ defaultClassNames.dropdown
82
+ ),
83
+ caption_label: cn(
84
+ "font-medium select-none",
85
+ captionLayout === "label"
86
+ ? "text-sm"
87
+ : "flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
88
+ defaultClassNames.caption_label
89
+ ),
90
+ month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
91
+ weekdays: cn("flex", defaultClassNames.weekdays),
92
+ weekday: cn(
93
+ "flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none",
94
+ defaultClassNames.weekday
95
+ ),
96
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
97
+ week_number_header: cn(
98
+ "w-(--cell-size) select-none",
99
+ defaultClassNames.week_number_header
100
+ ),
101
+ week_number: cn(
102
+ "text-[0.8rem] text-muted-foreground select-none",
103
+ defaultClassNames.week_number
104
+ ),
105
+ day: cn(
106
+ "group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)",
107
+ props.showWeekNumber
108
+ ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)"
109
+ : "[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)",
110
+ defaultClassNames.day
111
+ ),
112
+ range_start: cn(
113
+ "relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted",
114
+ defaultClassNames.range_start
115
+ ),
116
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
117
+ range_end: cn(
118
+ "relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted",
119
+ defaultClassNames.range_end
120
+ ),
121
+ today: cn(
122
+ "rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none",
123
+ defaultClassNames.today
124
+ ),
125
+ outside: cn(
126
+ "text-muted-foreground aria-selected:text-muted-foreground",
127
+ defaultClassNames.outside
128
+ ),
129
+ disabled: cn(
130
+ "text-muted-foreground opacity-50",
131
+ defaultClassNames.disabled
132
+ ),
133
+ hidden: cn("invisible", defaultClassNames.hidden),
134
+ ...classNames,
135
+ }}
136
+ components={{
137
+ Root: ({ className, rootRef, ...props }) => {
138
+ return (
139
+ <div
140
+ data-slot="calendar"
141
+ ref={rootRef}
142
+ className={cn(className)}
143
+ {...props}
144
+ />
145
+ )
146
+ },
147
+ Chevron: ({ className, orientation, ...props }) => {
148
+ if (orientation === "left") {
149
+ return (
150
+ <ChevronLeftIcon className={cn("size-4", className)} {...props} />
151
+ )
152
+ }
153
+
154
+ if (orientation === "right") {
155
+ return (
156
+ <ChevronRightIcon className={cn("size-4", className)} {...props} />
157
+ )
158
+ }
159
+
160
+ return (
161
+ <ChevronDownIcon className={cn("size-4", className)} {...props} />
162
+ )
163
+ },
164
+ DayButton: ({ ...props }) => (
165
+ <CalendarDayButton locale={locale} {...props} />
166
+ ),
167
+ WeekNumber: ({ children, ...props }) => {
168
+ return (
169
+ <td {...props}>
170
+ <div className="flex size-(--cell-size) items-center justify-center text-center">
171
+ {children}
172
+ </div>
173
+ </td>
174
+ )
175
+ },
176
+ ...components,
177
+ }}
178
+ {...props}
179
+ />
180
+ )
181
+ }
182
+
183
+ function CalendarDayButton({
184
+ className,
185
+ day,
186
+ modifiers,
187
+ locale,
188
+ ...props
189
+ }: React.ComponentProps<typeof DayButton> & { locale?: Partial<Locale> }) {
190
+ const defaultClassNames = getDefaultClassNames()
191
+
192
+ const ref = React.useRef<HTMLButtonElement>(null)
193
+ React.useEffect(() => {
194
+ if (modifiers.focused) ref.current?.focus()
195
+ }, [modifiers.focused])
196
+
197
+ return (
198
+ <Button
199
+ variant="ghost"
200
+ size="icon"
201
+ data-day={day.date.toLocaleDateString(locale?.code)}
202
+ data-selected-single={
203
+ modifiers.selected &&
204
+ !modifiers.range_start &&
205
+ !modifiers.range_end &&
206
+ !modifiers.range_middle
207
+ }
208
+ data-range-start={modifiers.range_start}
209
+ data-range-end={modifiers.range_end}
210
+ data-range-middle={modifiers.range_middle}
211
+ className={cn(
212
+ "relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-muted data-[range-middle=true]:text-foreground data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-foreground [&>span]:text-xs [&>span]:opacity-70",
213
+ defaultClassNames.day,
214
+ className
215
+ )}
216
+ {...props}
217
+ />
218
+ )
219
+ }
220
+
221
+ export { Calendar, CalendarDayButton }
@@ -0,0 +1,102 @@
1
+ import * as React from "react"
2
+ import { cn } from "cn"
3
+
4
+ function Card({
5
+ className,
6
+ size = "default",
7
+ ...props
8
+ }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
9
+ return (
10
+ <div
11
+ data-slot="card"
12
+ data-size={size}
13
+ className={cn(
14
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
23
+ return (
24
+ <div
25
+ data-slot="card-header"
26
+ className={cn(
27
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
28
+ className
29
+ )}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
36
+ return (
37
+ <div
38
+ data-slot="card-title"
39
+ className={cn(
40
+ "font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
41
+ className
42
+ )}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+
48
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
49
+ return (
50
+ <div
51
+ data-slot="card-description"
52
+ className={cn("text-sm text-muted-foreground", className)}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
59
+ return (
60
+ <div
61
+ data-slot="card-action"
62
+ className={cn(
63
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
64
+ className
65
+ )}
66
+ {...props}
67
+ />
68
+ )
69
+ }
70
+
71
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
72
+ return (
73
+ <div
74
+ data-slot="card-content"
75
+ className={cn("px-(--card-spacing)", className)}
76
+ {...props}
77
+ />
78
+ )
79
+ }
80
+
81
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
82
+ return (
83
+ <div
84
+ data-slot="card-footer"
85
+ className={cn(
86
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
87
+ className
88
+ )}
89
+ {...props}
90
+ />
91
+ )
92
+ }
93
+
94
+ export {
95
+ Card,
96
+ CardHeader,
97
+ CardFooter,
98
+ CardTitle,
99
+ CardAction,
100
+ CardDescription,
101
+ CardContent,
102
+ }
@@ -0,0 +1,28 @@
1
+ "use client"
2
+
3
+ import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
4
+ import { cn } from "cn"
5
+ import { CheckIcon } from "lucide-react"
6
+
7
+ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
8
+ return (
9
+ <CheckboxPrimitive.Root
10
+ data-slot="checkbox"
11
+ className={cn(
12
+ "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary",
13
+ className
14
+ )}
15
+ {...props}
16
+ >
17
+ <CheckboxPrimitive.Indicator
18
+ data-slot="checkbox-indicator"
19
+ className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
20
+ >
21
+ <CheckIcon
22
+ />
23
+ </CheckboxPrimitive.Indicator>
24
+ </CheckboxPrimitive.Root>
25
+ )
26
+ }
27
+
28
+ export { Checkbox }
@@ -0,0 +1,196 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Command as CommandPrimitive } from "cmdk"
5
+ import { cn } from "cn"
6
+
7
+ import {
8
+ Dialog,
9
+ DialogContent,
10
+ DialogDescription,
11
+ DialogHeader,
12
+ DialogTitle,
13
+ } from "@/components/ui/dialog"
14
+ import {
15
+ InputGroup,
16
+ InputGroupAddon,
17
+ } from "@/components/ui/input-group"
18
+ import { SearchIcon, CheckIcon } from "lucide-react"
19
+
20
+ function Command({
21
+ className,
22
+ ...props
23
+ }: React.ComponentProps<typeof CommandPrimitive>) {
24
+ return (
25
+ <CommandPrimitive
26
+ data-slot="command"
27
+ className={cn(
28
+ "flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",
29
+ className
30
+ )}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ function CommandDialog({
37
+ title = "Command Palette",
38
+ description = "Search for a command to run...",
39
+ children,
40
+ className,
41
+ showCloseButton = false,
42
+ ...props
43
+ }: Omit<React.ComponentProps<typeof Dialog>, "children"> & {
44
+ title?: string
45
+ description?: string
46
+ className?: string
47
+ showCloseButton?: boolean
48
+ children: React.ReactNode
49
+ }) {
50
+ return (
51
+ <Dialog {...props}>
52
+ <DialogHeader className="sr-only">
53
+ <DialogTitle>{title}</DialogTitle>
54
+ <DialogDescription>{description}</DialogDescription>
55
+ </DialogHeader>
56
+ <DialogContent
57
+ className={cn(
58
+ "top-1/3 translate-y-0 overflow-hidden rounded-xl! p-0",
59
+ className
60
+ )}
61
+ showCloseButton={showCloseButton}
62
+ >
63
+ {children}
64
+ </DialogContent>
65
+ </Dialog>
66
+ )
67
+ }
68
+
69
+ function CommandInput({
70
+ className,
71
+ ...props
72
+ }: React.ComponentProps<typeof CommandPrimitive.Input>) {
73
+ return (
74
+ <div data-slot="command-input-wrapper" className="p-1 pb-0">
75
+ <InputGroup className="h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!">
76
+ <CommandPrimitive.Input
77
+ data-slot="command-input"
78
+ className={cn(
79
+ "w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
80
+ className
81
+ )}
82
+ {...props}
83
+ />
84
+ <InputGroupAddon>
85
+ <SearchIcon className="size-4 shrink-0 opacity-50" />
86
+ </InputGroupAddon>
87
+ </InputGroup>
88
+ </div>
89
+ )
90
+ }
91
+
92
+ function CommandList({
93
+ className,
94
+ ...props
95
+ }: React.ComponentProps<typeof CommandPrimitive.List>) {
96
+ return (
97
+ <CommandPrimitive.List
98
+ data-slot="command-list"
99
+ className={cn(
100
+ "no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none",
101
+ className
102
+ )}
103
+ {...props}
104
+ />
105
+ )
106
+ }
107
+
108
+ function CommandEmpty({
109
+ className,
110
+ ...props
111
+ }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
112
+ return (
113
+ <CommandPrimitive.Empty
114
+ data-slot="command-empty"
115
+ className={cn("py-6 text-center text-sm", className)}
116
+ {...props}
117
+ />
118
+ )
119
+ }
120
+
121
+ function CommandGroup({
122
+ className,
123
+ ...props
124
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
125
+ return (
126
+ <CommandPrimitive.Group
127
+ data-slot="command-group"
128
+ className={cn(
129
+ "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",
130
+ className
131
+ )}
132
+ {...props}
133
+ />
134
+ )
135
+ }
136
+
137
+ function CommandSeparator({
138
+ className,
139
+ ...props
140
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
141
+ return (
142
+ <CommandPrimitive.Separator
143
+ data-slot="command-separator"
144
+ className={cn("-mx-1 h-px bg-border", className)}
145
+ {...props}
146
+ />
147
+ )
148
+ }
149
+
150
+ function CommandItem({
151
+ className,
152
+ children,
153
+ ...props
154
+ }: React.ComponentProps<typeof CommandPrimitive.Item>) {
155
+ return (
156
+ <CommandPrimitive.Item
157
+ data-slot="command-item"
158
+ className={cn(
159
+ "group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground",
160
+ className
161
+ )}
162
+ {...props}
163
+ >
164
+ {children}
165
+ <CheckIcon className="ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" />
166
+ </CommandPrimitive.Item>
167
+ )
168
+ }
169
+
170
+ function CommandShortcut({
171
+ className,
172
+ ...props
173
+ }: React.ComponentProps<"span">) {
174
+ return (
175
+ <span
176
+ data-slot="command-shortcut"
177
+ className={cn(
178
+ "ml-auto text-xs tracking-widest text-muted-foreground group-data-selected/command-item:text-foreground",
179
+ className
180
+ )}
181
+ {...props}
182
+ />
183
+ )
184
+ }
185
+
186
+ export {
187
+ Command,
188
+ CommandDialog,
189
+ CommandInput,
190
+ CommandList,
191
+ CommandEmpty,
192
+ CommandGroup,
193
+ CommandItem,
194
+ CommandShortcut,
195
+ CommandSeparator,
196
+ }