howone 0.0.3 → 0.0.6

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 (167) hide show
  1. package/package.json +1 -1
  2. package/templates/nextjs/.prettierignore +7 -0
  3. package/templates/nextjs/.prettierrc +11 -0
  4. package/templates/nextjs/README.md +12 -27
  5. package/templates/nextjs/app/globals.css +123 -40
  6. package/templates/nextjs/app/layout.tsx +19 -19
  7. package/templates/nextjs/app/page.tsx +13 -60
  8. package/templates/nextjs/bun.lock +925 -53
  9. package/templates/nextjs/components/.gitkeep +0 -0
  10. package/templates/nextjs/components/theme-provider.tsx +71 -0
  11. package/templates/nextjs/components/ui/accordion.tsx +81 -0
  12. package/templates/nextjs/components/ui/alert-dialog.tsx +199 -0
  13. package/templates/nextjs/components/ui/alert.tsx +76 -0
  14. package/templates/nextjs/components/ui/aspect-ratio.tsx +11 -0
  15. package/templates/nextjs/components/ui/avatar.tsx +112 -0
  16. package/templates/nextjs/components/ui/badge.tsx +49 -0
  17. package/templates/nextjs/components/ui/breadcrumb.tsx +122 -0
  18. package/templates/nextjs/components/ui/button-group.tsx +83 -0
  19. package/templates/nextjs/components/ui/button.tsx +67 -0
  20. package/templates/nextjs/components/ui/calendar.tsx +222 -0
  21. package/templates/nextjs/components/ui/card.tsx +103 -0
  22. package/templates/nextjs/components/ui/carousel.tsx +242 -0
  23. package/templates/nextjs/components/ui/chart.tsx +373 -0
  24. package/templates/nextjs/components/ui/checkbox.tsx +33 -0
  25. package/templates/nextjs/components/ui/collapsible.tsx +33 -0
  26. package/templates/nextjs/components/ui/combobox.tsx +299 -0
  27. package/templates/nextjs/components/ui/command.tsx +195 -0
  28. package/templates/nextjs/components/ui/context-menu.tsx +263 -0
  29. package/templates/nextjs/components/ui/dialog.tsx +168 -0
  30. package/templates/nextjs/components/ui/direction.tsx +22 -0
  31. package/templates/nextjs/components/ui/drawer.tsx +134 -0
  32. package/templates/nextjs/components/ui/dropdown-menu.tsx +269 -0
  33. package/templates/nextjs/components/ui/empty.tsx +104 -0
  34. package/templates/nextjs/components/ui/field.tsx +238 -0
  35. package/templates/nextjs/components/ui/hover-card.tsx +44 -0
  36. package/templates/nextjs/components/ui/input-group.tsx +156 -0
  37. package/templates/nextjs/components/ui/input-otp.tsx +87 -0
  38. package/templates/nextjs/components/ui/input.tsx +19 -0
  39. package/templates/nextjs/components/ui/item.tsx +196 -0
  40. package/templates/nextjs/components/ui/kbd.tsx +26 -0
  41. package/templates/nextjs/components/ui/label.tsx +24 -0
  42. package/templates/nextjs/components/ui/menubar.tsx +280 -0
  43. package/templates/nextjs/components/ui/native-select.tsx +61 -0
  44. package/templates/nextjs/components/ui/navigation-menu.tsx +164 -0
  45. package/templates/nextjs/components/ui/pagination.tsx +129 -0
  46. package/templates/nextjs/components/ui/popover.tsx +89 -0
  47. package/templates/nextjs/components/ui/progress.tsx +31 -0
  48. package/templates/nextjs/components/ui/radio-group.tsx +44 -0
  49. package/templates/nextjs/components/ui/resizable.tsx +50 -0
  50. package/templates/nextjs/components/ui/scroll-area.tsx +55 -0
  51. package/templates/nextjs/components/ui/select.tsx +192 -0
  52. package/templates/nextjs/components/ui/separator.tsx +28 -0
  53. package/templates/nextjs/components/ui/sheet.tsx +147 -0
  54. package/templates/nextjs/components/ui/sidebar.tsx +702 -0
  55. package/templates/nextjs/components/ui/skeleton.tsx +13 -0
  56. package/templates/nextjs/components/ui/slider.tsx +59 -0
  57. package/templates/nextjs/components/ui/sonner.tsx +49 -0
  58. package/templates/nextjs/components/ui/spinner.tsx +10 -0
  59. package/templates/nextjs/components/ui/switch.tsx +33 -0
  60. package/templates/nextjs/components/ui/table.tsx +116 -0
  61. package/templates/nextjs/components/ui/tabs.tsx +90 -0
  62. package/templates/nextjs/components/ui/textarea.tsx +18 -0
  63. package/templates/nextjs/components/ui/toggle-group.tsx +89 -0
  64. package/templates/nextjs/components/ui/toggle.tsx +47 -0
  65. package/templates/nextjs/components/ui/tooltip.tsx +57 -0
  66. package/templates/nextjs/components.json +25 -0
  67. package/templates/nextjs/hooks/.gitkeep +0 -0
  68. package/templates/nextjs/hooks/use-mobile.ts +19 -0
  69. package/templates/nextjs/lib/.gitkeep +0 -0
  70. package/templates/nextjs/lib/sdk.ts +7 -0
  71. package/templates/nextjs/lib/utils.ts +6 -0
  72. package/templates/nextjs/next.config.mjs +4 -0
  73. package/templates/vite/.prettierignore +7 -0
  74. package/templates/vite/.prettierrc +11 -0
  75. package/templates/vite/AGENTS.md +0 -0
  76. package/templates/vite/README.md +12 -64
  77. package/templates/vite/bun.lock +1478 -0
  78. package/templates/vite/components.json +25 -0
  79. package/templates/vite/eslint.config.js +1 -0
  80. package/templates/vite/index.html +2 -2
  81. package/templates/vite/package.json +39 -13
  82. package/templates/vite/public/vite.svg +1 -0
  83. package/templates/vite/src/App.tsx +6 -115
  84. package/templates/vite/src/components/theme-provider.tsx +230 -0
  85. package/templates/vite/src/components/ui/accordion.tsx +79 -0
  86. package/templates/vite/src/components/ui/alert-dialog.tsx +197 -0
  87. package/templates/vite/src/components/ui/alert.tsx +76 -0
  88. package/templates/vite/src/components/ui/aspect-ratio.tsx +11 -0
  89. package/templates/vite/src/components/ui/avatar.tsx +110 -0
  90. package/templates/vite/src/components/ui/badge.tsx +49 -0
  91. package/templates/vite/src/components/ui/breadcrumb.tsx +122 -0
  92. package/templates/vite/src/components/ui/button-group.tsx +83 -0
  93. package/templates/vite/src/components/ui/button.tsx +67 -0
  94. package/templates/vite/src/components/ui/calendar.tsx +222 -0
  95. package/templates/vite/src/components/ui/card.tsx +103 -0
  96. package/templates/vite/src/components/ui/carousel.tsx +240 -0
  97. package/templates/vite/src/components/ui/chart.tsx +373 -0
  98. package/templates/vite/src/components/ui/checkbox.tsx +31 -0
  99. package/templates/vite/src/components/ui/collapsible.tsx +33 -0
  100. package/templates/vite/src/components/ui/combobox.tsx +299 -0
  101. package/templates/vite/src/components/ui/command.tsx +193 -0
  102. package/templates/vite/src/components/ui/context-menu.tsx +261 -0
  103. package/templates/vite/src/components/ui/dialog.tsx +168 -0
  104. package/templates/vite/src/components/ui/direction.tsx +22 -0
  105. package/templates/vite/src/components/ui/drawer.tsx +132 -0
  106. package/templates/vite/src/components/ui/dropdown-menu.tsx +269 -0
  107. package/templates/vite/src/components/ui/empty.tsx +104 -0
  108. package/templates/vite/src/components/ui/field.tsx +238 -0
  109. package/templates/vite/src/components/ui/hover-card.tsx +42 -0
  110. package/templates/vite/src/components/ui/input-group.tsx +154 -0
  111. package/templates/vite/src/components/ui/input-otp.tsx +87 -0
  112. package/templates/vite/src/components/ui/input.tsx +19 -0
  113. package/templates/vite/src/components/ui/item.tsx +196 -0
  114. package/templates/vite/src/components/ui/kbd.tsx +26 -0
  115. package/templates/vite/src/components/ui/label.tsx +22 -0
  116. package/templates/vite/src/components/ui/menubar.tsx +280 -0
  117. package/templates/vite/src/components/ui/native-select.tsx +61 -0
  118. package/templates/vite/src/components/ui/navigation-menu.tsx +164 -0
  119. package/templates/vite/src/components/ui/pagination.tsx +129 -0
  120. package/templates/vite/src/components/ui/popover.tsx +87 -0
  121. package/templates/vite/src/components/ui/progress.tsx +31 -0
  122. package/templates/vite/src/components/ui/radio-group.tsx +42 -0
  123. package/templates/vite/src/components/ui/resizable.tsx +50 -0
  124. package/templates/vite/src/components/ui/scroll-area.tsx +53 -0
  125. package/templates/vite/src/components/ui/select.tsx +192 -0
  126. package/templates/vite/src/components/ui/separator.tsx +26 -0
  127. package/templates/vite/src/components/ui/sheet.tsx +145 -0
  128. package/templates/vite/src/components/ui/sidebar.tsx +700 -0
  129. package/templates/vite/src/components/ui/skeleton.tsx +13 -0
  130. package/templates/vite/src/components/ui/slider.tsx +59 -0
  131. package/templates/vite/src/components/ui/sonner.tsx +47 -0
  132. package/templates/vite/src/components/ui/spinner.tsx +10 -0
  133. package/templates/vite/src/components/ui/switch.tsx +33 -0
  134. package/templates/vite/src/components/ui/table.tsx +114 -0
  135. package/templates/vite/src/components/ui/tabs.tsx +90 -0
  136. package/templates/vite/src/components/ui/textarea.tsx +18 -0
  137. package/templates/vite/src/components/ui/toggle-group.tsx +89 -0
  138. package/templates/vite/src/components/ui/toggle.tsx +45 -0
  139. package/templates/vite/src/components/ui/tooltip.tsx +57 -0
  140. package/templates/vite/src/hooks/use-mobile.ts +19 -0
  141. package/templates/vite/src/index.css +125 -103
  142. package/templates/vite/src/lib/sdk.ts +7 -0
  143. package/templates/vite/src/lib/utils.ts +6 -0
  144. package/templates/vite/src/main.tsx +11 -7
  145. package/templates/vite/tsconfig.app.json +11 -4
  146. package/templates/vite/tsconfig.json +7 -1
  147. package/templates/vite/tsconfig.node.json +5 -3
  148. package/templates/vite/vite.config.ts +10 -3
  149. package/templates/nextjs/AGENTS.md +0 -5
  150. package/templates/nextjs/CLAUDE.md +0 -1
  151. package/templates/nextjs/app/page.module.css +0 -142
  152. package/templates/nextjs/gitignore +0 -41
  153. package/templates/nextjs/next-env.d.ts +0 -6
  154. package/templates/nextjs/next.config.ts +0 -7
  155. package/templates/nextjs/package.json +0 -32
  156. package/templates/nextjs/public/file.svg +0 -1
  157. package/templates/nextjs/public/globe.svg +0 -1
  158. package/templates/nextjs/public/next.svg +0 -1
  159. package/templates/nextjs/public/vercel.svg +0 -1
  160. package/templates/nextjs/public/window.svg +0 -1
  161. package/templates/nextjs/tsconfig.json +0 -34
  162. package/templates/vite/gitignore +0 -24
  163. package/templates/vite/public/favicon.svg +0 -1
  164. package/templates/vite/public/icons.svg +0 -24
  165. package/templates/vite/src/App.css +0 -184
  166. package/templates/vite/src/assets/hero.png +0 -0
  167. package/templates/vite/src/assets/vite.svg +0 -1
@@ -0,0 +1,154 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "@/lib/utils"
5
+ import { Button } from "@/components/ui/button"
6
+ import { Input } from "@/components/ui/input"
7
+ import { Textarea } from "@/components/ui/textarea"
8
+
9
+ function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
10
+ return (
11
+ <div
12
+ data-slot="input-group"
13
+ role="group"
14
+ className={cn(
15
+ "group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ const inputGroupAddonVariants = cva(
24
+ "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
25
+ {
26
+ variants: {
27
+ align: {
28
+ "inline-start":
29
+ "order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]",
30
+ "inline-end":
31
+ "order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]",
32
+ "block-start":
33
+ "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
34
+ "block-end":
35
+ "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2",
36
+ },
37
+ },
38
+ defaultVariants: {
39
+ align: "inline-start",
40
+ },
41
+ }
42
+ )
43
+
44
+ function InputGroupAddon({
45
+ className,
46
+ align = "inline-start",
47
+ ...props
48
+ }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
49
+ return (
50
+ <div
51
+ role="group"
52
+ data-slot="input-group-addon"
53
+ data-align={align}
54
+ className={cn(inputGroupAddonVariants({ align }), className)}
55
+ onClick={(e) => {
56
+ if ((e.target as HTMLElement).closest("button")) {
57
+ return
58
+ }
59
+ e.currentTarget.parentElement?.querySelector("input")?.focus()
60
+ }}
61
+ {...props}
62
+ />
63
+ )
64
+ }
65
+
66
+ const inputGroupButtonVariants = cva(
67
+ "flex items-center gap-2 text-sm shadow-none",
68
+ {
69
+ variants: {
70
+ size: {
71
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
72
+ sm: "",
73
+ "icon-xs":
74
+ "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
75
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0",
76
+ },
77
+ },
78
+ defaultVariants: {
79
+ size: "xs",
80
+ },
81
+ }
82
+ )
83
+
84
+ function InputGroupButton({
85
+ className,
86
+ type = "button",
87
+ variant = "ghost",
88
+ size = "xs",
89
+ ...props
90
+ }: Omit<React.ComponentProps<typeof Button>, "size"> &
91
+ VariantProps<typeof inputGroupButtonVariants>) {
92
+ return (
93
+ <Button
94
+ type={type}
95
+ data-size={size}
96
+ variant={variant}
97
+ className={cn(inputGroupButtonVariants({ size }), className)}
98
+ {...props}
99
+ />
100
+ )
101
+ }
102
+
103
+ function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
104
+ return (
105
+ <span
106
+ className={cn(
107
+ "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
108
+ className
109
+ )}
110
+ {...props}
111
+ />
112
+ )
113
+ }
114
+
115
+ function InputGroupInput({
116
+ className,
117
+ ...props
118
+ }: React.ComponentProps<"input">) {
119
+ return (
120
+ <Input
121
+ data-slot="input-group-control"
122
+ className={cn(
123
+ "flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent",
124
+ className
125
+ )}
126
+ {...props}
127
+ />
128
+ )
129
+ }
130
+
131
+ function InputGroupTextarea({
132
+ className,
133
+ ...props
134
+ }: React.ComponentProps<"textarea">) {
135
+ return (
136
+ <Textarea
137
+ data-slot="input-group-control"
138
+ className={cn(
139
+ "flex-1 resize-none rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent",
140
+ className
141
+ )}
142
+ {...props}
143
+ />
144
+ )
145
+ }
146
+
147
+ export {
148
+ InputGroup,
149
+ InputGroupAddon,
150
+ InputGroupButton,
151
+ InputGroupText,
152
+ InputGroupInput,
153
+ InputGroupTextarea,
154
+ }
@@ -0,0 +1,87 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { OTPInput, OTPInputContext } from "input-otp"
5
+
6
+ import { cn } from "@/lib/utils"
7
+ import { MinusIcon } from "lucide-react"
8
+
9
+ function InputOTP({
10
+ className,
11
+ containerClassName,
12
+ ...props
13
+ }: React.ComponentProps<typeof OTPInput> & {
14
+ containerClassName?: string
15
+ }) {
16
+ return (
17
+ <OTPInput
18
+ data-slot="input-otp"
19
+ containerClassName={cn(
20
+ "cn-input-otp flex items-center has-disabled:opacity-50",
21
+ containerClassName
22
+ )}
23
+ spellCheck={false}
24
+ className={cn("disabled:cursor-not-allowed", className)}
25
+ {...props}
26
+ />
27
+ )
28
+ }
29
+
30
+ function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
31
+ return (
32
+ <div
33
+ data-slot="input-otp-group"
34
+ className={cn(
35
+ "flex items-center rounded-lg has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40",
36
+ className
37
+ )}
38
+ {...props}
39
+ />
40
+ )
41
+ }
42
+
43
+ function InputOTPSlot({
44
+ index,
45
+ className,
46
+ ...props
47
+ }: React.ComponentProps<"div"> & {
48
+ index: number
49
+ }) {
50
+ const inputOTPContext = React.useContext(OTPInputContext)
51
+ const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}
52
+
53
+ return (
54
+ <div
55
+ data-slot="input-otp-slot"
56
+ data-active={isActive}
57
+ className={cn(
58
+ "relative flex size-8 items-center justify-center border-y border-r border-input text-sm transition-all outline-none first:rounded-l-lg first:border-l last:rounded-r-lg aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-3 data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40",
59
+ className
60
+ )}
61
+ {...props}
62
+ >
63
+ {char}
64
+ {hasFakeCaret && (
65
+ <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
66
+ <div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
67
+ </div>
68
+ )}
69
+ </div>
70
+ )
71
+ }
72
+
73
+ function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
74
+ return (
75
+ <div
76
+ data-slot="input-otp-separator"
77
+ className="flex items-center [&_svg:not([class*='size-'])]:size-4"
78
+ role="separator"
79
+ {...props}
80
+ >
81
+ <MinusIcon
82
+ />
83
+ </div>
84
+ )
85
+ }
86
+
87
+ export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
6
+ return (
7
+ <input
8
+ type={type}
9
+ data-slot="input"
10
+ className={cn(
11
+ "h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
12
+ className
13
+ )}
14
+ {...props}
15
+ />
16
+ )
17
+ }
18
+
19
+ export { Input }
@@ -0,0 +1,196 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "@/lib/utils"
6
+ import { Separator } from "@/components/ui/separator"
7
+
8
+ function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
9
+ return (
10
+ <div
11
+ role="list"
12
+ data-slot="item-group"
13
+ className={cn(
14
+ "group/item-group flex w-full flex-col gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ function ItemSeparator({
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<typeof Separator>) {
26
+ return (
27
+ <Separator
28
+ data-slot="item-separator"
29
+ orientation="horizontal"
30
+ className={cn("my-2", className)}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ const itemVariants = cva(
37
+ "group/item flex w-full flex-wrap items-center rounded-lg border text-sm transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors [a]:hover:bg-muted",
38
+ {
39
+ variants: {
40
+ variant: {
41
+ default: "border-transparent",
42
+ outline: "border-border",
43
+ muted: "border-transparent bg-muted/50",
44
+ },
45
+ size: {
46
+ default: "gap-2.5 px-3 py-2.5",
47
+ sm: "gap-2.5 px-3 py-2.5",
48
+ xs: "gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0",
49
+ },
50
+ },
51
+ defaultVariants: {
52
+ variant: "default",
53
+ size: "default",
54
+ },
55
+ }
56
+ )
57
+
58
+ function Item({
59
+ className,
60
+ variant = "default",
61
+ size = "default",
62
+ asChild = false,
63
+ ...props
64
+ }: React.ComponentProps<"div"> &
65
+ VariantProps<typeof itemVariants> & { asChild?: boolean }) {
66
+ const Comp = asChild ? Slot.Root : "div"
67
+ return (
68
+ <Comp
69
+ data-slot="item"
70
+ data-variant={variant}
71
+ data-size={size}
72
+ className={cn(itemVariants({ variant, size, className }))}
73
+ {...props}
74
+ />
75
+ )
76
+ }
77
+
78
+ const itemMediaVariants = cva(
79
+ "flex shrink-0 items-center justify-center gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start [&_svg]:pointer-events-none",
80
+ {
81
+ variants: {
82
+ variant: {
83
+ default: "bg-transparent",
84
+ icon: "[&_svg:not([class*='size-'])]:size-4",
85
+ image:
86
+ "size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover",
87
+ },
88
+ },
89
+ defaultVariants: {
90
+ variant: "default",
91
+ },
92
+ }
93
+ )
94
+
95
+ function ItemMedia({
96
+ className,
97
+ variant = "default",
98
+ ...props
99
+ }: React.ComponentProps<"div"> & VariantProps<typeof itemMediaVariants>) {
100
+ return (
101
+ <div
102
+ data-slot="item-media"
103
+ data-variant={variant}
104
+ className={cn(itemMediaVariants({ variant, className }))}
105
+ {...props}
106
+ />
107
+ )
108
+ }
109
+
110
+ function ItemContent({ className, ...props }: React.ComponentProps<"div">) {
111
+ return (
112
+ <div
113
+ data-slot="item-content"
114
+ className={cn(
115
+ "flex flex-1 flex-col gap-1 group-data-[size=xs]/item:gap-0 [&+[data-slot=item-content]]:flex-none",
116
+ className
117
+ )}
118
+ {...props}
119
+ />
120
+ )
121
+ }
122
+
123
+ function ItemTitle({ className, ...props }: React.ComponentProps<"div">) {
124
+ return (
125
+ <div
126
+ data-slot="item-title"
127
+ className={cn(
128
+ "line-clamp-1 flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4",
129
+ className
130
+ )}
131
+ {...props}
132
+ />
133
+ )
134
+ }
135
+
136
+ function ItemDescription({ className, ...props }: React.ComponentProps<"p">) {
137
+ return (
138
+ <p
139
+ data-slot="item-description"
140
+ className={cn(
141
+ "line-clamp-2 text-left text-sm leading-normal font-normal text-muted-foreground group-data-[size=xs]/item:text-xs [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
142
+ className
143
+ )}
144
+ {...props}
145
+ />
146
+ )
147
+ }
148
+
149
+ function ItemActions({ className, ...props }: React.ComponentProps<"div">) {
150
+ return (
151
+ <div
152
+ data-slot="item-actions"
153
+ className={cn("flex items-center gap-2", className)}
154
+ {...props}
155
+ />
156
+ )
157
+ }
158
+
159
+ function ItemHeader({ className, ...props }: React.ComponentProps<"div">) {
160
+ return (
161
+ <div
162
+ data-slot="item-header"
163
+ className={cn(
164
+ "flex basis-full items-center justify-between gap-2",
165
+ className
166
+ )}
167
+ {...props}
168
+ />
169
+ )
170
+ }
171
+
172
+ function ItemFooter({ className, ...props }: React.ComponentProps<"div">) {
173
+ return (
174
+ <div
175
+ data-slot="item-footer"
176
+ className={cn(
177
+ "flex basis-full items-center justify-between gap-2",
178
+ className
179
+ )}
180
+ {...props}
181
+ />
182
+ )
183
+ }
184
+
185
+ export {
186
+ Item,
187
+ ItemMedia,
188
+ ItemContent,
189
+ ItemActions,
190
+ ItemGroup,
191
+ ItemSeparator,
192
+ ItemTitle,
193
+ ItemDescription,
194
+ ItemHeader,
195
+ ItemFooter,
196
+ }
@@ -0,0 +1,26 @@
1
+ import { cn } from "@/lib/utils"
2
+
3
+ function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
4
+ return (
5
+ <kbd
6
+ data-slot="kbd"
7
+ className={cn(
8
+ "pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none in-data-[slot=tooltip-content]:bg-background/20 in-data-[slot=tooltip-content]:text-background dark:in-data-[slot=tooltip-content]:bg-background/10 [&_svg:not([class*='size-'])]:size-3",
9
+ className
10
+ )}
11
+ {...props}
12
+ />
13
+ )
14
+ }
15
+
16
+ function KbdGroup({ className, ...props }: React.ComponentProps<"div">) {
17
+ return (
18
+ <kbd
19
+ data-slot="kbd-group"
20
+ className={cn("inline-flex items-center gap-1", className)}
21
+ {...props}
22
+ />
23
+ )
24
+ }
25
+
26
+ export { Kbd, KbdGroup }
@@ -0,0 +1,22 @@
1
+ import * as React from "react"
2
+ import { Label as LabelPrimitive } from "radix-ui"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ function Label({
7
+ className,
8
+ ...props
9
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
10
+ return (
11
+ <LabelPrimitive.Root
12
+ data-slot="label"
13
+ className={cn(
14
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ export { Label }