@turtleclub/ui 0.3.0-beta.8 → 0.3.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 (302) hide show
  1. package/.prettierrc.json +4 -0
  2. package/.turbo/turbo-build.log +152 -26
  3. package/CHANGELOG.md +338 -0
  4. package/dist/index.cjs +178 -36
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.js +25526 -4757
  7. package/dist/index.js.map +1 -1
  8. package/dist/styles.css +1 -1
  9. package/dist/types/components/features/data-table.d.ts +9 -0
  10. package/dist/types/components/features/data-table.d.ts.map +1 -0
  11. package/dist/types/components/features/index.d.ts +5 -0
  12. package/dist/types/components/features/index.d.ts.map +1 -0
  13. package/dist/types/components/features/page-heading.d.ts +10 -0
  14. package/dist/types/components/features/page-heading.d.ts.map +1 -0
  15. package/dist/types/components/features/search-bar.d.ts +10 -0
  16. package/dist/types/components/features/search-bar.d.ts.map +1 -0
  17. package/dist/types/components/features/segmented-navigation.d.ts +7 -0
  18. package/dist/types/components/features/segmented-navigation.d.ts.map +1 -0
  19. package/dist/types/components/features/sidebar-layout.d.ts +36 -0
  20. package/dist/types/components/features/sidebar-layout.d.ts.map +1 -0
  21. package/dist/types/components/icons/arrow.d.ts +4 -0
  22. package/dist/types/components/icons/arrow.d.ts.map +1 -0
  23. package/dist/types/components/icons/beta.d.ts +4 -0
  24. package/dist/types/components/icons/beta.d.ts.map +1 -0
  25. package/dist/types/components/icons/dot.d.ts +4 -0
  26. package/dist/types/components/icons/dot.d.ts.map +1 -0
  27. package/dist/types/components/icons/index.d.ts +8 -0
  28. package/dist/types/components/icons/index.d.ts.map +1 -0
  29. package/dist/types/components/icons/issue.d.ts +4 -0
  30. package/dist/types/components/icons/issue.d.ts.map +1 -0
  31. package/dist/types/components/icons/turtle.d.ts +4 -0
  32. package/dist/types/components/icons/turtle.d.ts.map +1 -0
  33. package/dist/types/components/icons/update.d.ts +4 -0
  34. package/dist/types/components/icons/update.d.ts.map +1 -0
  35. package/dist/types/components/icons/warning.d.ts +4 -0
  36. package/dist/types/components/icons/warning.d.ts.map +1 -0
  37. package/dist/types/components/molecules/index.d.ts +2 -0
  38. package/dist/types/components/molecules/index.d.ts.map +1 -1
  39. package/dist/types/components/molecules/opportunity/index.d.ts +3 -1
  40. package/dist/types/components/molecules/opportunity/index.d.ts.map +1 -1
  41. package/dist/types/components/molecules/opportunity/opportunity-apr.d.ts +8 -3
  42. package/dist/types/components/molecules/opportunity/opportunity-apr.d.ts.map +1 -1
  43. package/dist/types/components/molecules/opportunity/opportunity-disclaimer.d.ts +1 -2
  44. package/dist/types/components/molecules/opportunity/opportunity-disclaimer.d.ts.map +1 -1
  45. package/dist/types/components/molecules/opportunity/opportunity-list/hooks/index.d.ts +3 -0
  46. package/dist/types/components/molecules/opportunity/opportunity-list/hooks/index.d.ts.map +1 -0
  47. package/dist/types/components/molecules/opportunity/opportunity-list/hooks/use-opportunity-filtering.d.ts +11 -0
  48. package/dist/types/components/molecules/opportunity/opportunity-list/hooks/use-opportunity-filtering.d.ts.map +1 -0
  49. package/dist/types/components/molecules/opportunity/opportunity-list/hooks/use-opportunity-grouping.d.ts +9 -0
  50. package/dist/types/components/molecules/opportunity/opportunity-list/hooks/use-opportunity-grouping.d.ts.map +1 -0
  51. package/dist/types/components/molecules/opportunity/opportunity-list/index.d.ts +2 -0
  52. package/dist/types/components/molecules/opportunity/opportunity-list/index.d.ts.map +1 -0
  53. package/dist/types/components/molecules/opportunity/opportunity-list/opportunity-list.d.ts +22 -0
  54. package/dist/types/components/molecules/opportunity/opportunity-list/opportunity-list.d.ts.map +1 -0
  55. package/dist/types/components/molecules/opportunity/opportunity-rate-estimator.d.ts +1 -2
  56. package/dist/types/components/molecules/opportunity/opportunity-rate-estimator.d.ts.map +1 -1
  57. package/dist/types/components/molecules/opportunity/opportunity-section.d.ts +4 -0
  58. package/dist/types/components/molecules/opportunity/opportunity-section.d.ts.map +1 -1
  59. package/dist/types/components/molecules/opportunity/opportunity-selector.d.ts +1 -2
  60. package/dist/types/components/molecules/opportunity/opportunity-selector.d.ts.map +1 -1
  61. package/dist/types/components/molecules/opportunity/opportunity-type.d.ts +1 -2
  62. package/dist/types/components/molecules/opportunity/opportunity-type.d.ts.map +1 -1
  63. package/dist/types/components/molecules/route-details.d.ts +1 -1
  64. package/dist/types/components/molecules/route-details.d.ts.map +1 -1
  65. package/dist/types/components/molecules/slippage-selector.d.ts +1 -2
  66. package/dist/types/components/molecules/slippage-selector.d.ts.map +1 -1
  67. package/dist/types/components/molecules/swap-details.d.ts.map +1 -1
  68. package/dist/types/components/molecules/swap-input.d.ts +5 -1
  69. package/dist/types/components/molecules/swap-input.d.ts.map +1 -1
  70. package/dist/types/components/molecules/tabs.d.ts +18 -0
  71. package/dist/types/components/molecules/tabs.d.ts.map +1 -0
  72. package/dist/types/components/molecules/token-selector.d.ts +1 -1
  73. package/dist/types/components/molecules/token-selector.d.ts.map +1 -1
  74. package/dist/types/components/molecules/tx-status.d.ts.map +1 -1
  75. package/dist/types/components/molecules/widget/asset-list/asset-filters.d.ts +20 -0
  76. package/dist/types/components/molecules/widget/asset-list/asset-filters.d.ts.map +1 -0
  77. package/dist/types/components/molecules/widget/asset-list/asset-list.d.ts +35 -0
  78. package/dist/types/components/molecules/widget/asset-list/asset-list.d.ts.map +1 -0
  79. package/dist/types/components/molecules/widget/asset-list/asset-row.d.ts +12 -0
  80. package/dist/types/components/molecules/widget/asset-list/asset-row.d.ts.map +1 -0
  81. package/dist/types/components/molecules/widget/asset-list/hooks/index.d.ts +3 -0
  82. package/dist/types/components/molecules/widget/asset-list/hooks/index.d.ts.map +1 -0
  83. package/dist/types/components/molecules/widget/asset-list/hooks/use-asset-filtering.d.ts +10 -0
  84. package/dist/types/components/molecules/widget/asset-list/hooks/use-asset-filtering.d.ts.map +1 -0
  85. package/dist/types/components/molecules/widget/asset-list/hooks/use-asset-grouping.d.ts +9 -0
  86. package/dist/types/components/molecules/widget/asset-list/hooks/use-asset-grouping.d.ts.map +1 -0
  87. package/dist/types/components/molecules/widget/asset-list/index.d.ts +4 -0
  88. package/dist/types/components/molecules/widget/asset-list/index.d.ts.map +1 -0
  89. package/dist/types/components/molecules/widget/base-selector.d.ts +17 -0
  90. package/dist/types/components/molecules/widget/base-selector.d.ts.map +1 -0
  91. package/dist/types/components/molecules/widget/campaign-item.d.ts +20 -0
  92. package/dist/types/components/molecules/widget/campaign-item.d.ts.map +1 -0
  93. package/dist/types/components/molecules/widget/deal-item.d.ts +20 -0
  94. package/dist/types/components/molecules/widget/deal-item.d.ts.map +1 -0
  95. package/dist/types/components/molecules/widget/index.d.ts +14 -0
  96. package/dist/types/components/molecules/widget/index.d.ts.map +1 -0
  97. package/dist/types/components/molecules/widget/opportunity-item.d.ts +33 -0
  98. package/dist/types/components/molecules/widget/opportunity-item.d.ts.map +1 -0
  99. package/dist/types/components/molecules/widget/widget-item-stats.d.ts +14 -0
  100. package/dist/types/components/molecules/widget/widget-item-stats.d.ts.map +1 -0
  101. package/dist/types/components/molecules/widget/widget-item.d.ts +26 -0
  102. package/dist/types/components/molecules/widget/widget-item.d.ts.map +1 -0
  103. package/dist/types/components/molecules/widget/widget-list-items.d.ts +20 -0
  104. package/dist/types/components/molecules/widget/widget-list-items.d.ts.map +1 -0
  105. package/dist/types/components/ui/alert-dialog.d.ts +15 -0
  106. package/dist/types/components/ui/alert-dialog.d.ts.map +1 -0
  107. package/dist/types/components/ui/animated-background/animated-background.d.ts +9 -0
  108. package/dist/types/components/ui/animated-background/animated-background.d.ts.map +1 -0
  109. package/dist/types/components/ui/animated-background/index.d.ts +2 -0
  110. package/dist/types/components/ui/animated-background/index.d.ts.map +1 -0
  111. package/dist/types/components/ui/avatar.d.ts +18 -4
  112. package/dist/types/components/ui/avatar.d.ts.map +1 -1
  113. package/dist/types/components/ui/badge.d.ts +5 -4
  114. package/dist/types/components/ui/badge.d.ts.map +1 -1
  115. package/dist/types/components/ui/banner.d.ts +7 -0
  116. package/dist/types/components/ui/banner.d.ts.map +1 -0
  117. package/dist/types/components/ui/button.d.ts +8 -6
  118. package/dist/types/components/ui/button.d.ts.map +1 -1
  119. package/dist/types/components/ui/card.d.ts +10 -11
  120. package/dist/types/components/ui/card.d.ts.map +1 -1
  121. package/dist/types/components/ui/checkbox.d.ts +5 -0
  122. package/dist/types/components/ui/checkbox.d.ts.map +1 -0
  123. package/dist/types/components/ui/chip.d.ts +1 -1
  124. package/dist/types/components/ui/chip.d.ts.map +1 -1
  125. package/dist/types/components/ui/collapsible.d.ts +7 -0
  126. package/dist/types/components/ui/collapsible.d.ts.map +1 -0
  127. package/dist/types/components/ui/combobox.d.ts +148 -0
  128. package/dist/types/components/ui/combobox.d.ts.map +1 -0
  129. package/dist/types/components/ui/command.d.ts +19 -0
  130. package/dist/types/components/ui/command.d.ts.map +1 -0
  131. package/dist/types/components/ui/dialog.d.ts +10 -10
  132. package/dist/types/components/ui/dialog.d.ts.map +1 -1
  133. package/dist/types/components/ui/dropdown.d.ts +30 -0
  134. package/dist/types/components/ui/dropdown.d.ts.map +1 -0
  135. package/dist/types/components/ui/field.d.ts +26 -0
  136. package/dist/types/components/ui/field.d.ts.map +1 -0
  137. package/dist/types/components/ui/heading.d.ts +12 -0
  138. package/dist/types/components/ui/heading.d.ts.map +1 -0
  139. package/dist/types/components/ui/hover-card.d.ts +7 -7
  140. package/dist/types/components/ui/hover-card.d.ts.map +1 -1
  141. package/dist/types/components/ui/icon-animation.d.ts +1 -1
  142. package/dist/types/components/ui/icon-animation.d.ts.map +1 -1
  143. package/dist/types/components/ui/icon-list.d.ts +17 -0
  144. package/dist/types/components/ui/icon-list.d.ts.map +1 -0
  145. package/dist/types/components/ui/index.d.ts +28 -8
  146. package/dist/types/components/ui/index.d.ts.map +1 -1
  147. package/dist/types/components/ui/info-card.d.ts +4 -4
  148. package/dist/types/components/ui/info-card.d.ts.map +1 -1
  149. package/dist/types/components/ui/input-group.d.ts +17 -0
  150. package/dist/types/components/ui/input-group.d.ts.map +1 -0
  151. package/dist/types/components/ui/input.d.ts +1 -3
  152. package/dist/types/components/ui/input.d.ts.map +1 -1
  153. package/dist/types/components/ui/label-with-icon.d.ts +3 -3
  154. package/dist/types/components/ui/label-with-icon.d.ts.map +1 -1
  155. package/dist/types/components/ui/label.d.ts +1 -1
  156. package/dist/types/components/ui/label.d.ts.map +1 -1
  157. package/dist/types/components/ui/multi-select.d.ts +192 -0
  158. package/dist/types/components/ui/multi-select.d.ts.map +1 -0
  159. package/dist/types/components/ui/navigation-bar.d.ts +2 -2
  160. package/dist/types/components/ui/navigation-bar.d.ts.map +1 -1
  161. package/dist/types/components/ui/navigation-menu.d.ts +15 -0
  162. package/dist/types/components/ui/navigation-menu.d.ts.map +1 -0
  163. package/dist/types/components/ui/opportunity-details-v1.d.ts +1 -1
  164. package/dist/types/components/ui/opportunity-details-v1.d.ts.map +1 -1
  165. package/dist/types/components/ui/popover.d.ts +8 -0
  166. package/dist/types/components/ui/popover.d.ts.map +1 -0
  167. package/dist/types/components/ui/scroll-area.d.ts +2 -2
  168. package/dist/types/components/ui/scroll-area.d.ts.map +1 -1
  169. package/dist/types/components/ui/segment-control.d.ts +19 -0
  170. package/dist/types/components/ui/segment-control.d.ts.map +1 -0
  171. package/dist/types/components/ui/select.d.ts +14 -13
  172. package/dist/types/components/ui/select.d.ts.map +1 -1
  173. package/dist/types/components/ui/separator.d.ts +1 -1
  174. package/dist/types/components/ui/separator.d.ts.map +1 -1
  175. package/dist/types/components/ui/sheet.d.ts +14 -0
  176. package/dist/types/components/ui/sheet.d.ts.map +1 -0
  177. package/dist/types/components/ui/sidebar.d.ts +69 -0
  178. package/dist/types/components/ui/sidebar.d.ts.map +1 -0
  179. package/dist/types/components/ui/skeleton.d.ts +4 -0
  180. package/dist/types/components/ui/skeleton.d.ts.map +1 -0
  181. package/dist/types/components/ui/slider.d.ts +5 -0
  182. package/dist/types/components/ui/slider.d.ts.map +1 -0
  183. package/dist/types/components/ui/sonner.d.ts +1 -2
  184. package/dist/types/components/ui/sonner.d.ts.map +1 -1
  185. package/dist/types/components/ui/switch.d.ts +1 -1
  186. package/dist/types/components/ui/switch.d.ts.map +1 -1
  187. package/dist/types/components/ui/table-shadcn.d.ts +11 -0
  188. package/dist/types/components/ui/table-shadcn.d.ts.map +1 -0
  189. package/dist/types/components/ui/table.d.ts +2 -2
  190. package/dist/types/components/ui/table.d.ts.map +1 -1
  191. package/dist/types/components/ui/textarea.d.ts +4 -0
  192. package/dist/types/components/ui/textarea.d.ts.map +1 -0
  193. package/dist/types/components/ui/toggle-group.d.ts +2 -2
  194. package/dist/types/components/ui/toggle-group.d.ts.map +1 -1
  195. package/dist/types/components/ui/toggle.d.ts +2 -2
  196. package/dist/types/components/ui/toggle.d.ts.map +1 -1
  197. package/dist/types/components/ui/tooltip.d.ts +7 -4
  198. package/dist/types/components/ui/tooltip.d.ts.map +1 -1
  199. package/dist/types/hooks/useIsMobile.d.ts +7 -0
  200. package/dist/types/hooks/useIsMobile.d.ts.map +1 -0
  201. package/dist/types/index.d.ts +2 -0
  202. package/dist/types/index.d.ts.map +1 -1
  203. package/package.json +39 -28
  204. package/src/components/features/data-table.tsx +96 -0
  205. package/src/components/features/index.ts +4 -0
  206. package/src/components/features/page-heading.tsx +22 -0
  207. package/src/components/features/search-bar.tsx +50 -0
  208. package/src/components/features/segmented-navigation.tsx +18 -0
  209. package/src/components/features/sidebar-layout.tsx +190 -0
  210. package/src/components/icons/arrow.tsx +23 -0
  211. package/src/components/icons/beta.tsx +86 -0
  212. package/src/components/icons/dot.tsx +89 -0
  213. package/src/components/icons/index.ts +7 -0
  214. package/src/components/icons/issue.tsx +97 -0
  215. package/src/components/icons/turtle.tsx +143 -0
  216. package/src/components/icons/update.tsx +108 -0
  217. package/src/components/icons/warning.tsx +86 -0
  218. package/src/components/molecules/index.ts +2 -1
  219. package/src/components/molecules/opportunity/index.ts +5 -1
  220. package/src/components/molecules/opportunity/opportunity-apr.tsx +99 -16
  221. package/src/components/molecules/opportunity/opportunity-list/hooks/index.ts +2 -0
  222. package/src/components/molecules/opportunity/opportunity-list/hooks/use-opportunity-filtering.ts +45 -0
  223. package/src/components/molecules/opportunity/opportunity-list/hooks/use-opportunity-grouping.ts +81 -0
  224. package/src/components/molecules/opportunity/opportunity-list/index.ts +1 -0
  225. package/src/components/molecules/opportunity/opportunity-list/opportunity-list.tsx +136 -0
  226. package/src/components/molecules/opportunity/opportunity-rate-estimator.tsx +4 -1
  227. package/src/components/molecules/opportunity/opportunity-section.tsx +37 -19
  228. package/src/components/molecules/opportunity/opportunity-selector.tsx +2 -3
  229. package/src/components/molecules/route-details.tsx +48 -37
  230. package/src/components/molecules/swap-details.tsx +2 -4
  231. package/src/components/molecules/swap-input.tsx +56 -21
  232. package/src/components/molecules/tabs.tsx +67 -0
  233. package/src/components/molecules/token-selector.tsx +2 -2
  234. package/src/components/molecules/tx-status.tsx +1 -5
  235. package/src/components/molecules/widget/asset-list/asset-filters.tsx +111 -0
  236. package/src/components/molecules/widget/asset-list/asset-list.tsx +171 -0
  237. package/src/components/molecules/widget/asset-list/asset-row.tsx +45 -0
  238. package/src/components/molecules/widget/asset-list/hooks/index.ts +2 -0
  239. package/src/components/molecules/widget/asset-list/hooks/use-asset-filtering.ts +42 -0
  240. package/src/components/molecules/widget/asset-list/hooks/use-asset-grouping.ts +78 -0
  241. package/src/components/molecules/widget/asset-list/index.ts +3 -0
  242. package/src/components/molecules/widget/base-selector.tsx +104 -0
  243. package/src/components/molecules/widget/campaign-item.tsx +76 -0
  244. package/src/components/molecules/widget/deal-item.tsx +80 -0
  245. package/src/components/molecules/widget/index.ts +33 -0
  246. package/src/components/molecules/widget/opportunity-item.tsx +91 -0
  247. package/src/components/molecules/widget/widget-item-stats.tsx +50 -0
  248. package/src/components/molecules/widget/widget-item.tsx +138 -0
  249. package/src/components/molecules/widget/widget-list-items.tsx +86 -0
  250. package/src/components/ui/alert-dialog.tsx +146 -0
  251. package/src/components/ui/animated-background/animated-background.tsx +174 -0
  252. package/src/components/ui/animated-background/index.ts +1 -0
  253. package/src/components/ui/avatar.tsx +34 -19
  254. package/src/components/ui/badge.tsx +18 -8
  255. package/src/components/ui/banner.tsx +78 -0
  256. package/src/components/ui/button.tsx +51 -21
  257. package/src/components/ui/card.tsx +21 -61
  258. package/src/components/ui/checkbox.tsx +29 -0
  259. package/src/components/ui/collapsible.tsx +22 -0
  260. package/src/components/ui/combobox.tsx +617 -0
  261. package/src/components/ui/command.tsx +164 -0
  262. package/src/components/ui/dialog.tsx +5 -9
  263. package/src/components/ui/dropdown.tsx +263 -0
  264. package/src/components/ui/field.tsx +232 -0
  265. package/src/components/ui/heading.tsx +49 -0
  266. package/src/components/ui/hover-card.tsx +10 -10
  267. package/src/components/ui/icon-list.tsx +141 -0
  268. package/src/components/ui/index.ts +29 -9
  269. package/src/components/ui/info-card.tsx +1 -1
  270. package/src/components/ui/input-group.tsx +158 -0
  271. package/src/components/ui/input.tsx +17 -25
  272. package/src/components/ui/label-with-icon.tsx +40 -30
  273. package/src/components/ui/label.tsx +8 -9
  274. package/src/components/ui/multi-select.tsx +1000 -0
  275. package/src/components/ui/navigation-menu.tsx +181 -0
  276. package/src/components/ui/opportunity-details-v1.tsx +2 -2
  277. package/src/components/ui/popover.tsx +42 -0
  278. package/src/components/ui/scroll-area.tsx +11 -11
  279. package/src/components/ui/segment-control.tsx +140 -0
  280. package/src/components/ui/select.tsx +26 -31
  281. package/src/components/ui/sheet.tsx +130 -0
  282. package/src/components/ui/sidebar.tsx +693 -0
  283. package/src/components/ui/skeleton.tsx +14 -0
  284. package/src/components/ui/slider.tsx +58 -0
  285. package/src/components/ui/switch.tsx +8 -11
  286. package/src/components/ui/{table-shad.tsx → table-shadcn.tsx} +25 -39
  287. package/src/components/ui/table.tsx +3 -2
  288. package/src/components/ui/textarea.tsx +22 -0
  289. package/src/components/ui/tooltip.tsx +11 -7
  290. package/src/hooks/useIsMobile.ts +74 -0
  291. package/src/index.ts +2 -0
  292. package/src/styles/globals.css +87 -20
  293. package/src/styles/themes/semantic.css +11 -5
  294. package/src/styles/tokens/colors.css +64 -53
  295. package/src/styles/tokens/radius.css +3 -34
  296. package/tsconfig.json +11 -15
  297. package/vite.config.js +41 -57
  298. package/dist/types/components/molecules/opportunity/opportunity-item.d.ts +0 -15
  299. package/dist/types/components/molecules/opportunity/opportunity-item.d.ts.map +0 -1
  300. package/dist/types/components/ui/table-shad.d.ts +0 -11
  301. package/dist/types/components/ui/table-shad.d.ts.map +0 -1
  302. package/src/components/molecules/opportunity/opportunity-item.tsx +0 -93
@@ -0,0 +1,164 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Command as CommandPrimitive } from "cmdk";
5
+ import { SearchIcon } from "lucide-react";
6
+
7
+ import { cn } from "@/lib/utils";
8
+ import {
9
+ Dialog,
10
+ DialogContent,
11
+ DialogDescription,
12
+ DialogHeader,
13
+ DialogTitle,
14
+ } from "@/components/ui/dialog";
15
+
16
+ function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {
17
+ return (
18
+ <CommandPrimitive
19
+ data-slot="command"
20
+ className={cn(
21
+ "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
22
+ className
23
+ )}
24
+ {...props}
25
+ />
26
+ );
27
+ }
28
+
29
+ function CommandDialog({
30
+ title = "Command Palette",
31
+ description = "Search for a command to run...",
32
+ children,
33
+ className,
34
+ showCloseButton = true,
35
+ ...props
36
+ }: React.ComponentProps<typeof Dialog> & {
37
+ title?: string;
38
+ description?: string;
39
+ className?: string;
40
+ showCloseButton?: boolean;
41
+ }) {
42
+ return (
43
+ <Dialog {...props}>
44
+ <DialogHeader className="sr-only">
45
+ <DialogTitle>{title}</DialogTitle>
46
+ <DialogDescription>{description}</DialogDescription>
47
+ </DialogHeader>
48
+ <DialogContent
49
+ className={cn("overflow-hidden p-0", className)}
50
+ showCloseButton={showCloseButton}
51
+ >
52
+ <Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
53
+ {children}
54
+ </Command>
55
+ </DialogContent>
56
+ </Dialog>
57
+ );
58
+ }
59
+
60
+ function CommandInput({
61
+ className,
62
+ ...props
63
+ }: React.ComponentProps<typeof CommandPrimitive.Input>) {
64
+ return (
65
+ <div
66
+ data-slot="command-input-wrapper"
67
+ className="border-border flex h-9 items-center gap-2 border-b px-3"
68
+ >
69
+ <SearchIcon className="size-4 shrink-0 opacity-50" />
70
+ <CommandPrimitive.Input
71
+ data-slot="command-input"
72
+ className={cn(
73
+ "placeholder:text-muted-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
74
+ className
75
+ )}
76
+ {...props}
77
+ />
78
+ </div>
79
+ );
80
+ }
81
+
82
+ function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>) {
83
+ return (
84
+ <CommandPrimitive.List
85
+ data-slot="command-list"
86
+ className={cn("max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto", className)}
87
+ {...props}
88
+ />
89
+ );
90
+ }
91
+
92
+ function CommandEmpty({ ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
93
+ return (
94
+ <CommandPrimitive.Empty
95
+ data-slot="command-empty"
96
+ className="py-6 text-center text-sm"
97
+ {...props}
98
+ />
99
+ );
100
+ }
101
+
102
+ function CommandGroup({
103
+ className,
104
+ ...props
105
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
106
+ return (
107
+ <CommandPrimitive.Group
108
+ data-slot="command-group"
109
+ className={cn(
110
+ "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
111
+ className
112
+ )}
113
+ {...props}
114
+ />
115
+ );
116
+ }
117
+
118
+ function CommandSeparator({
119
+ className,
120
+ ...props
121
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
122
+ return (
123
+ <CommandPrimitive.Separator
124
+ data-slot="command-separator"
125
+ className={cn("bg-border -mx-1 h-px", className)}
126
+ {...props}
127
+ />
128
+ );
129
+ }
130
+
131
+ function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {
132
+ return (
133
+ <CommandPrimitive.Item
134
+ data-slot="command-item"
135
+ className={cn(
136
+ "data-[selected=true]:bg-secondary data-[selected=true]:text-secondary-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
137
+ className
138
+ )}
139
+ {...props}
140
+ />
141
+ );
142
+ }
143
+
144
+ function CommandShortcut({ className, ...props }: React.ComponentProps<"span">) {
145
+ return (
146
+ <span
147
+ data-slot="command-shortcut"
148
+ className={cn("text-muted-foreground ml-auto text-xs tracking-widest", className)}
149
+ {...props}
150
+ />
151
+ );
152
+ }
153
+
154
+ export {
155
+ Command,
156
+ CommandDialog,
157
+ CommandInput,
158
+ CommandList,
159
+ CommandEmpty,
160
+ CommandGroup,
161
+ CommandItem,
162
+ CommandShortcut,
163
+ CommandSeparator,
164
+ };
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import * as React from "react";
2
4
  import * as DialogPrimitive from "@radix-ui/react-dialog";
3
5
  import { XIcon } from "lucide-react";
@@ -13,13 +15,7 @@ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive
13
15
  }
14
16
 
15
17
  function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
16
- return (
17
- <DialogPrimitive.Portal
18
- container={document.querySelectorAll(".turtle-widget-root")[0] ?? undefined}
19
- data-slot="dialog-portal"
20
- {...props}
21
- />
22
- );
18
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
23
19
  }
24
20
 
25
21
  function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
@@ -52,11 +48,11 @@ function DialogContent({
52
48
  }) {
53
49
  return (
54
50
  <DialogPortal data-slot="dialog-portal">
55
- <DialogOverlay />
51
+ <DialogOverlay className="backdrop-blur-sm" />
56
52
  <DialogPrimitive.Content
57
53
  data-slot="dialog-content"
58
54
  className={cn(
59
- "bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
55
+ "bg-background 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 border-gradient-soft fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg p-6 shadow-lg duration-200 sm:max-w-lg",
60
56
  className
61
57
  )}
62
58
  {...props}
@@ -0,0 +1,263 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
+ import { CheckIcon, ChevronDownIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
6
+ import { cn } from "@/lib/utils";
7
+
8
+ function DropdownMenu({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Root> & { className?: string }) {
12
+ return (
13
+ <div className={cn("relative z-10", className)}>
14
+ <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
15
+ </div>
16
+ );
17
+ }
18
+
19
+ function DropdownMenuPortal({
20
+ ...props
21
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
22
+ return (
23
+ <DropdownMenuPrimitive.Portal
24
+ data-slot="dropdown-menu-portal"
25
+ {...props}
26
+ container={document.querySelectorAll(".turtle-widget-root")[0] ?? undefined}
27
+ />
28
+ );
29
+ }
30
+
31
+ function DropdownMenuTrigger({
32
+ className,
33
+ children,
34
+ src,
35
+ ...props
36
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger> & {
37
+ src?: string;
38
+ }) {
39
+ return (
40
+ <DropdownMenuPrimitive.Trigger
41
+ data-slot="dropdown-menu-trigger"
42
+ className={cn(
43
+ "border-border bg-background flex max-h-10 min-w-[8rem] items-center rounded-full border outline-none",
44
+
45
+ className
46
+ )}
47
+ {...props}
48
+ >
49
+ {src ? (
50
+ <img src={src} alt={""} className="aspect-square h-full max-h-[38px] rounded-full" />
51
+ ) : undefined}
52
+ <div className={cn("grow py-2 pr-2.5", src ? "pl-2.5" : "pl-4")}>{children}</div>
53
+ <ChevronDownIcon className="mr-2.5 size-4" />
54
+ </DropdownMenuPrimitive.Trigger>
55
+ );
56
+ }
57
+
58
+ function DropdownMenuContent({
59
+ className,
60
+ sideOffset = 4,
61
+ ...props
62
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
63
+ return (
64
+ <DropdownMenuPrimitive.Portal
65
+ container={document.querySelectorAll(".turtle-widget-root")[0] ?? undefined}
66
+ >
67
+ <DropdownMenuPrimitive.Content
68
+ data-slot="dropdown-menu-content"
69
+ sideOffset={sideOffset}
70
+ className={cn(
71
+ "bg-background text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border-border z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg border p-1 shadow-md",
72
+ className
73
+ )}
74
+ {...props}
75
+ />
76
+ </DropdownMenuPrimitive.Portal>
77
+ );
78
+ }
79
+
80
+ function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
81
+ return <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
82
+ }
83
+
84
+ function DropdownMenuItem({
85
+ className,
86
+ inset,
87
+ variant = "default",
88
+ ...props
89
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
90
+ inset?: boolean;
91
+ variant?: "default" | "destructive";
92
+ }) {
93
+ return (
94
+ <DropdownMenuPrimitive.Item
95
+ data-slot="dropdown-menu-item"
96
+ data-inset={inset}
97
+ data-variant={variant}
98
+ className={cn(
99
+ "focus:bg-secondary focus:text-secondary-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-lg px-3 py-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
100
+ className
101
+ )}
102
+ {...props}
103
+ />
104
+ );
105
+ }
106
+
107
+ function DropdownMenuCheckboxItem({
108
+ className,
109
+ children,
110
+ checked,
111
+ ...props
112
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
113
+ return (
114
+ <DropdownMenuPrimitive.CheckboxItem
115
+ data-slot="dropdown-menu-checkbox-item"
116
+ className={cn(
117
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
118
+ className
119
+ )}
120
+ checked={checked}
121
+ {...props}
122
+ >
123
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
124
+ <DropdownMenuPrimitive.ItemIndicator>
125
+ <CheckIcon className="size-4" />
126
+ </DropdownMenuPrimitive.ItemIndicator>
127
+ </span>
128
+ {children}
129
+ </DropdownMenuPrimitive.CheckboxItem>
130
+ );
131
+ }
132
+
133
+ function DropdownMenuRadioGroup({
134
+ ...props
135
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
136
+ return <DropdownMenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
137
+ }
138
+
139
+ function DropdownMenuRadioItem({
140
+ className,
141
+ children,
142
+ ...props
143
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
144
+ return (
145
+ <DropdownMenuPrimitive.RadioItem
146
+ data-slot="dropdown-menu-radio-item"
147
+ className={cn(
148
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
149
+ className
150
+ )}
151
+ {...props}
152
+ >
153
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
154
+ <DropdownMenuPrimitive.ItemIndicator>
155
+ <CircleIcon className="size-2 fill-current" />
156
+ </DropdownMenuPrimitive.ItemIndicator>
157
+ </span>
158
+ {children}
159
+ </DropdownMenuPrimitive.RadioItem>
160
+ );
161
+ }
162
+
163
+ function DropdownMenuLabel({
164
+ className,
165
+ inset,
166
+ ...props
167
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
168
+ inset?: boolean;
169
+ }) {
170
+ return (
171
+ <DropdownMenuPrimitive.Label
172
+ data-slot="dropdown-menu-label"
173
+ data-inset={inset}
174
+ className={cn("px-2 py-1.5 text-sm font-medium data-[inset]:pl-8", className)}
175
+ {...props}
176
+ />
177
+ );
178
+ }
179
+
180
+ function DropdownMenuSeparator({
181
+ className,
182
+ ...props
183
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
184
+ return (
185
+ <DropdownMenuPrimitive.Separator
186
+ data-slot="dropdown-menu-separator"
187
+ className={cn("bg-border -mx-1 my-1 h-px", className)}
188
+ {...props}
189
+ />
190
+ );
191
+ }
192
+
193
+ function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<"span">) {
194
+ return (
195
+ <span
196
+ data-slot="dropdown-menu-shortcut"
197
+ className={cn("text-muted-foreground ml-auto text-xs tracking-widest", className)}
198
+ {...props}
199
+ />
200
+ );
201
+ }
202
+
203
+ function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
204
+ return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
205
+ }
206
+
207
+ function DropdownMenuSubTrigger({
208
+ className,
209
+ inset,
210
+ children,
211
+ ...props
212
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
213
+ inset?: boolean;
214
+ }) {
215
+ return (
216
+ <DropdownMenuPrimitive.SubTrigger
217
+ data-slot="dropdown-menu-sub-trigger"
218
+ data-inset={inset}
219
+ className={cn(
220
+ "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
221
+ className
222
+ )}
223
+ {...props}
224
+ >
225
+ {children}
226
+ <ChevronRightIcon className="ml-auto size-4" />
227
+ </DropdownMenuPrimitive.SubTrigger>
228
+ );
229
+ }
230
+
231
+ function DropdownMenuSubContent({
232
+ className,
233
+ ...props
234
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
235
+ return (
236
+ <DropdownMenuPrimitive.SubContent
237
+ data-slot="dropdown-menu-sub-content"
238
+ className={cn(
239
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
240
+ className
241
+ )}
242
+ {...props}
243
+ />
244
+ );
245
+ }
246
+
247
+ export {
248
+ DropdownMenu,
249
+ DropdownMenuPortal,
250
+ DropdownMenuTrigger,
251
+ DropdownMenuContent,
252
+ DropdownMenuGroup,
253
+ DropdownMenuLabel,
254
+ DropdownMenuItem,
255
+ DropdownMenuCheckboxItem,
256
+ DropdownMenuRadioGroup,
257
+ DropdownMenuRadioItem,
258
+ DropdownMenuSeparator,
259
+ DropdownMenuShortcut,
260
+ DropdownMenuSub,
261
+ DropdownMenuSubTrigger,
262
+ DropdownMenuSubContent,
263
+ };
@@ -0,0 +1,232 @@
1
+ "use client";
2
+
3
+ import React, { useMemo } from "react";
4
+ import { cva, type VariantProps } from "class-variance-authority";
5
+
6
+ import { cn } from "@/lib/utils";
7
+ import { Label } from "@/components/ui/label";
8
+ import { Separator } from "@/components/ui/separator";
9
+
10
+ function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
11
+ return (
12
+ <fieldset
13
+ data-slot="field-set"
14
+ className={cn(
15
+ "flex flex-col gap-6",
16
+ "has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ function FieldLegend({
25
+ className,
26
+ variant = "legend",
27
+ ...props
28
+ }: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) {
29
+ return (
30
+ <legend
31
+ data-slot="field-legend"
32
+ data-variant={variant}
33
+ className={cn(
34
+ "mb-3 font-medium",
35
+ "data-[variant=legend]:text-base",
36
+ "data-[variant=label]:text-sm",
37
+ className
38
+ )}
39
+ {...props}
40
+ />
41
+ );
42
+ }
43
+
44
+ function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
45
+ return (
46
+ <div
47
+ data-slot="field-group"
48
+ className={cn(
49
+ "group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4",
50
+ className
51
+ )}
52
+ {...props}
53
+ />
54
+ );
55
+ }
56
+
57
+ const fieldVariants = cva("group/field data-[invalid=true]:text-destructive flex w-full gap-3", {
58
+ variants: {
59
+ orientation: {
60
+ vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"],
61
+ horizontal: [
62
+ "flex-row items-center",
63
+ "[&>[data-slot=field-label]]:flex-auto",
64
+ "has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
65
+ ],
66
+ responsive: [
67
+ "flex-col @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto",
68
+ "@md/field-group:[&>[data-slot=field-label]]:flex-auto",
69
+ "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
70
+ ],
71
+ },
72
+ },
73
+ defaultVariants: {
74
+ orientation: "vertical",
75
+ },
76
+ });
77
+
78
+ function Field({
79
+ className,
80
+ orientation = "vertical",
81
+ ...props
82
+ }: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) {
83
+ return (
84
+ <div
85
+ role="group"
86
+ data-slot="field"
87
+ data-orientation={orientation}
88
+ className={cn(fieldVariants({ orientation }), className)}
89
+ {...props}
90
+ />
91
+ );
92
+ }
93
+
94
+ function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
95
+ return (
96
+ <div
97
+ data-slot="field-content"
98
+ className={cn("group/field-content flex flex-1 flex-col gap-1.5 leading-snug", className)}
99
+ {...props}
100
+ />
101
+ );
102
+ }
103
+
104
+ function FieldLabel({ className, ...props }: React.ComponentProps<typeof Label>) {
105
+ return (
106
+ <Label
107
+ data-slot="field-label"
108
+ className={cn(
109
+ "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50",
110
+ "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4",
111
+ "has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10",
112
+ className
113
+ )}
114
+ {...props}
115
+ />
116
+ );
117
+ }
118
+
119
+ function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
120
+ return (
121
+ <div
122
+ data-slot="field-label"
123
+ className={cn(
124
+ "flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50",
125
+ className
126
+ )}
127
+ {...props}
128
+ />
129
+ );
130
+ }
131
+
132
+ function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
133
+ return (
134
+ <p
135
+ data-slot="field-description"
136
+ className={cn(
137
+ "text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance",
138
+ "last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5",
139
+ "[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
140
+ className
141
+ )}
142
+ {...props}
143
+ />
144
+ );
145
+ }
146
+
147
+ function FieldSeparator({
148
+ children,
149
+ className,
150
+ ...props
151
+ }: React.ComponentProps<"div"> & {
152
+ children?: React.ReactNode;
153
+ }) {
154
+ return (
155
+ <div
156
+ data-slot="field-separator"
157
+ data-content={!!children}
158
+ className={cn(
159
+ "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
160
+ className
161
+ )}
162
+ {...props}
163
+ >
164
+ <Separator className="absolute inset-0 top-1/2" />
165
+ {children && (
166
+ <span
167
+ className="bg-background text-muted-foreground relative mx-auto block w-fit px-2"
168
+ data-slot="field-separator-content"
169
+ >
170
+ {children}
171
+ </span>
172
+ )}
173
+ </div>
174
+ );
175
+ }
176
+
177
+ function FieldError({
178
+ className,
179
+ children,
180
+ errors,
181
+ ...props
182
+ }: React.ComponentProps<"div"> & {
183
+ errors?: Array<{ message?: string } | undefined>;
184
+ }) {
185
+ const content = useMemo(() => {
186
+ if (children) {
187
+ return children;
188
+ }
189
+
190
+ if (!errors) {
191
+ return null;
192
+ }
193
+
194
+ if (errors?.length === 1 && errors[0]?.message) {
195
+ return errors[0].message;
196
+ }
197
+
198
+ return (
199
+ <ul className="ml-4 flex list-disc flex-col gap-1">
200
+ {errors.map((error, index) => error?.message && <li key={index}>{error.message}</li>)}
201
+ </ul>
202
+ );
203
+ }, [children, errors]);
204
+
205
+ if (!content) {
206
+ return null;
207
+ }
208
+
209
+ return (
210
+ <div
211
+ role="alert"
212
+ data-slot="field-error"
213
+ className={cn("text-destructive text-sm font-normal", className)}
214
+ {...props}
215
+ >
216
+ {content}
217
+ </div>
218
+ );
219
+ }
220
+
221
+ export {
222
+ Field,
223
+ FieldLabel,
224
+ FieldDescription,
225
+ FieldError,
226
+ FieldGroup,
227
+ FieldLegend,
228
+ FieldSeparator,
229
+ FieldSet,
230
+ FieldContent,
231
+ FieldTitle,
232
+ };