gladvn 0.2.22 → 0.2.27

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 (463) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -58
  3. package/bin/cli.js +352 -150
  4. package/llms.txt +7 -5
  5. package/package.json +14 -26
  6. package/src/blocks/auth-card.tsx +104 -0
  7. package/src/blocks/auth-dialog.tsx +116 -0
  8. package/src/blocks/auth-recovery.tsx +61 -0
  9. package/src/blocks/auth-split.tsx +132 -0
  10. package/src/blocks/dashboard.tsx +182 -0
  11. package/src/blocks/settings.tsx +104 -0
  12. package/src/components/macro/accordion-preset.tsx +2 -1
  13. package/src/components/macro/alert-dialog-preset.tsx +3 -2
  14. package/src/components/macro/alert-preset.tsx +2 -1
  15. package/src/components/macro/avatar-preset.tsx +2 -1
  16. package/src/components/macro/breadcrumb-preset.tsx +2 -1
  17. package/src/components/macro/card-preset.tsx +2 -1
  18. package/src/components/macro/carousel-preset.tsx +2 -1
  19. package/src/components/macro/checkbox-preset.tsx +2 -1
  20. package/src/components/macro/combobox-preset.tsx +5 -3
  21. package/src/components/macro/command-preset.tsx +7 -4
  22. package/src/components/macro/date-picker.tsx +3 -2
  23. package/src/components/macro/dialog-preset.tsx +3 -2
  24. package/src/components/macro/empty-preset.tsx +2 -1
  25. package/src/components/macro/field-preset.tsx +2 -1
  26. package/src/components/macro/input-otp-preset.tsx +2 -1
  27. package/src/components/macro/input-preset.tsx +2 -1
  28. package/src/components/macro/pagination-preset.tsx +2 -1
  29. package/src/components/macro/progress-preset.tsx +2 -1
  30. package/src/components/macro/select-preset.tsx +3 -2
  31. package/src/components/macro/slider-preset.tsx +2 -1
  32. package/src/components/macro/switch-preset.tsx +2 -1
  33. package/src/components/macro/tabs-preset.tsx +2 -1
  34. package/src/components/micro/accordion.test.tsx +96 -0
  35. package/src/components/micro/alert-dialog.tsx +1 -1
  36. package/src/components/micro/alert.test.tsx +77 -0
  37. package/src/components/micro/avatar.tsx +1 -1
  38. package/src/components/micro/badge.test.tsx +57 -0
  39. package/src/components/micro/breadcrumb.tsx +1 -1
  40. package/src/components/micro/button.test.tsx +101 -4
  41. package/src/components/micro/card.test.tsx +54 -0
  42. package/src/components/micro/card.tsx +1 -1
  43. package/src/components/micro/carousel.tsx +1 -1
  44. package/src/components/micro/chart.tsx +1 -1
  45. package/src/components/micro/checkbox.test.tsx +92 -0
  46. package/src/components/micro/combobox.tsx +1 -1
  47. package/src/components/micro/command.tsx +1 -1
  48. package/src/components/micro/context-menu.tsx +1 -1
  49. package/src/components/micro/dialog.test.tsx +127 -0
  50. package/src/components/micro/dialog.tsx +1 -1
  51. package/src/components/micro/direction.tsx +1 -1
  52. package/src/components/micro/drawer.tsx +2 -2
  53. package/src/components/micro/dropdown-menu.test.tsx +132 -0
  54. package/src/components/micro/dropdown-menu.tsx +1 -1
  55. package/src/components/micro/empty.tsx +1 -1
  56. package/src/components/micro/field.tsx +1 -1
  57. package/src/components/micro/input-group.tsx +1 -1
  58. package/src/components/micro/input.test.tsx +95 -0
  59. package/src/components/micro/item.tsx +1 -1
  60. package/src/components/micro/menubar.tsx +1 -1
  61. package/src/components/micro/navigation-menu.tsx +1 -1
  62. package/src/components/micro/pagination.tsx +1 -1
  63. package/src/components/micro/popover.test.tsx +83 -0
  64. package/src/components/micro/popover.tsx +1 -1
  65. package/src/components/micro/progress.tsx +1 -1
  66. package/src/components/micro/select.test.tsx +122 -0
  67. package/src/components/micro/select.tsx +1 -1
  68. package/src/components/micro/sheet.test.tsx +122 -0
  69. package/src/components/micro/sheet.tsx +1 -1
  70. package/src/components/micro/sidebar.tsx +1 -1
  71. package/src/components/micro/switch.test.tsx +108 -0
  72. package/src/components/micro/table.tsx +1 -1
  73. package/src/components/micro/tabs.test.tsx +90 -0
  74. package/src/components/micro/tooltip.test.tsx +107 -0
  75. package/src/components/micro/tooltip.tsx +1 -1
  76. package/src/dev/data.ts +8 -0
  77. package/src/dev/main.tsx +4 -0
  78. package/src/dev/showcase/accordion.tsx +4 -2
  79. package/src/dev/showcase/alert-dialog.tsx +7 -4
  80. package/src/dev/showcase/alert.tsx +6 -3
  81. package/src/dev/showcase/aspect-ratio.tsx +2 -1
  82. package/src/dev/showcase/avatar.tsx +6 -3
  83. package/src/dev/showcase/badge.tsx +2 -1
  84. package/src/dev/showcase/breadcrumb.tsx +7 -4
  85. package/src/dev/showcase/button.tsx +2 -1
  86. package/src/dev/showcase/calendar.tsx +2 -1
  87. package/src/dev/showcase/card.tsx +4 -2
  88. package/src/dev/showcase/carousel.tsx +4 -2
  89. package/src/dev/showcase/chart.tsx +4 -2
  90. package/src/dev/showcase/checkbox.tsx +4 -2
  91. package/src/dev/showcase/collapsible.tsx +4 -2
  92. package/src/dev/showcase/combobox.tsx +9 -5
  93. package/src/dev/showcase/command.tsx +6 -3
  94. package/src/dev/showcase/context-menu.tsx +5 -3
  95. package/src/dev/showcase/dialog.tsx +5 -3
  96. package/src/dev/showcase/drawer.tsx +5 -3
  97. package/src/dev/showcase/dropdown-menu.tsx +7 -4
  98. package/src/dev/showcase/empty.tsx +6 -3
  99. package/src/dev/showcase/hover-card.tsx +7 -4
  100. package/src/dev/showcase/input-group.tsx +6 -3
  101. package/src/dev/showcase/input-otp.tsx +6 -3
  102. package/src/dev/showcase/input.tsx +6 -3
  103. package/src/dev/showcase/item.tsx +4 -2
  104. package/src/dev/showcase/kbd.tsx +10 -6
  105. package/src/dev/showcase/label.tsx +2 -1
  106. package/src/dev/showcase/menubar.tsx +5 -3
  107. package/src/dev/showcase/navigation-menu.tsx +5 -3
  108. package/src/dev/showcase/overview.tsx +9 -5
  109. package/src/dev/showcase/pagination.tsx +4 -2
  110. package/src/dev/showcase/popover.tsx +5 -3
  111. package/src/dev/showcase/progress.tsx +4 -2
  112. package/src/dev/showcase/radio-group.tsx +2 -1
  113. package/src/dev/showcase/resizable.tsx +4 -2
  114. package/src/dev/showcase/scroll-area.tsx +2 -1
  115. package/src/dev/showcase/select.tsx +7 -4
  116. package/src/dev/showcase/separator.tsx +2 -1
  117. package/src/dev/showcase/sheet.tsx +5 -3
  118. package/src/dev/showcase/sidebar.tsx +4 -2
  119. package/src/dev/showcase/skeleton.tsx +2 -1
  120. package/src/dev/showcase/slider.tsx +6 -3
  121. package/src/dev/showcase/sonner.tsx +2 -1
  122. package/src/dev/showcase/spinner.tsx +2 -1
  123. package/src/dev/showcase/switch.tsx +2 -1
  124. package/src/dev/showcase/table.tsx +4 -2
  125. package/src/dev/showcase/tabs.tsx +4 -2
  126. package/src/dev/showcase/textarea.tsx +6 -3
  127. package/src/dev/showcase/toast.tsx +2 -1
  128. package/src/dev/showcase/toggle-group.tsx +6 -3
  129. package/src/dev/showcase/toggle.tsx +2 -1
  130. package/src/dev/showcase/tooltip.tsx +5 -3
  131. package/src/dev/showcase/why.tsx +271 -0
  132. package/src/hooks/use-mobile.test.ts +72 -0
  133. package/src/lib/utils.test.ts +26 -10
  134. package/src/styles/gladvn.css +0 -1
  135. package/src/styles/tokens.css +4 -0
  136. package/dist/components/macro/accordion-preset.d.ts +0 -14
  137. package/dist/components/macro/accordion-preset.d.ts.map +0 -1
  138. package/dist/components/macro/alert-dialog-preset.d.ts +0 -26
  139. package/dist/components/macro/alert-dialog-preset.d.ts.map +0 -1
  140. package/dist/components/macro/alert-preset.d.ts +0 -14
  141. package/dist/components/macro/alert-preset.d.ts.map +0 -1
  142. package/dist/components/macro/avatar-preset.d.ts +0 -11
  143. package/dist/components/macro/avatar-preset.d.ts.map +0 -1
  144. package/dist/components/macro/breadcrumb-preset.d.ts +0 -12
  145. package/dist/components/macro/breadcrumb-preset.d.ts.map +0 -1
  146. package/dist/components/macro/card-preset.d.ts +0 -10
  147. package/dist/components/macro/card-preset.d.ts.map +0 -1
  148. package/dist/components/macro/carousel-preset.d.ts +0 -18
  149. package/dist/components/macro/carousel-preset.d.ts.map +0 -1
  150. package/dist/components/macro/checkbox-preset.d.ts +0 -14
  151. package/dist/components/macro/checkbox-preset.d.ts.map +0 -1
  152. package/dist/components/macro/combobox-preset.d.ts +0 -27
  153. package/dist/components/macro/combobox-preset.d.ts.map +0 -1
  154. package/dist/components/macro/command-preset.d.ts +0 -16
  155. package/dist/components/macro/command-preset.d.ts.map +0 -1
  156. package/dist/components/macro/date-picker.d.ts +0 -62
  157. package/dist/components/macro/date-picker.d.ts.map +0 -1
  158. package/dist/components/macro/dialog-preset.d.ts +0 -24
  159. package/dist/components/macro/dialog-preset.d.ts.map +0 -1
  160. package/dist/components/macro/empty-preset.d.ts +0 -15
  161. package/dist/components/macro/empty-preset.d.ts.map +0 -1
  162. package/dist/components/macro/field-preset.d.ts +0 -15
  163. package/dist/components/macro/field-preset.d.ts.map +0 -1
  164. package/dist/components/macro/index.d.ts +0 -22
  165. package/dist/components/macro/index.d.ts.map +0 -1
  166. package/dist/components/macro/input-otp-preset.d.ts +0 -19
  167. package/dist/components/macro/input-otp-preset.d.ts.map +0 -1
  168. package/dist/components/macro/input-preset.d.ts +0 -21
  169. package/dist/components/macro/input-preset.d.ts.map +0 -1
  170. package/dist/components/macro/pagination-preset.d.ts +0 -13
  171. package/dist/components/macro/pagination-preset.d.ts.map +0 -1
  172. package/dist/components/macro/progress-preset.d.ts +0 -10
  173. package/dist/components/macro/progress-preset.d.ts.map +0 -1
  174. package/dist/components/macro/radio-group-preset.d.ts +0 -22
  175. package/dist/components/macro/radio-group-preset.d.ts.map +0 -1
  176. package/dist/components/macro/select-preset.d.ts +0 -42
  177. package/dist/components/macro/select-preset.d.ts.map +0 -1
  178. package/dist/components/macro/slider-preset.d.ts +0 -12
  179. package/dist/components/macro/slider-preset.d.ts.map +0 -1
  180. package/dist/components/macro/switch-preset.d.ts +0 -12
  181. package/dist/components/macro/switch-preset.d.ts.map +0 -1
  182. package/dist/components/macro/tabs-preset.d.ts +0 -17
  183. package/dist/components/macro/tabs-preset.d.ts.map +0 -1
  184. package/dist/components/macro/textarea-preset.d.ts +0 -17
  185. package/dist/components/macro/textarea-preset.d.ts.map +0 -1
  186. package/dist/components/micro/accordion.d.ts +0 -15
  187. package/dist/components/micro/accordion.d.ts.map +0 -1
  188. package/dist/components/micro/alert-dialog.d.ts +0 -33
  189. package/dist/components/micro/alert-dialog.d.ts.map +0 -1
  190. package/dist/components/micro/alert.d.ts +0 -35
  191. package/dist/components/micro/alert.d.ts.map +0 -1
  192. package/dist/components/micro/aspect-ratio.d.ts +0 -20
  193. package/dist/components/micro/aspect-ratio.d.ts.map +0 -1
  194. package/dist/components/micro/avatar.d.ts +0 -23
  195. package/dist/components/micro/avatar.d.ts.map +0 -1
  196. package/dist/components/micro/badge.d.ts +0 -23
  197. package/dist/components/micro/badge.d.ts.map +0 -1
  198. package/dist/components/micro/breadcrumb.d.ts +0 -31
  199. package/dist/components/micro/breadcrumb.d.ts.map +0 -1
  200. package/dist/components/micro/button.d.ts +0 -46
  201. package/dist/components/micro/button.d.ts.map +0 -1
  202. package/dist/components/micro/calendar.d.ts +0 -28
  203. package/dist/components/micro/calendar.d.ts.map +0 -1
  204. package/dist/components/micro/card.d.ts +0 -28
  205. package/dist/components/micro/card.d.ts.map +0 -1
  206. package/dist/components/micro/carousel.d.ts +0 -29
  207. package/dist/components/micro/carousel.d.ts.map +0 -1
  208. package/dist/components/micro/chart.d.ts +0 -49
  209. package/dist/components/micro/chart.d.ts.map +0 -1
  210. package/dist/components/micro/checkbox.d.ts +0 -17
  211. package/dist/components/micro/checkbox.d.ts.map +0 -1
  212. package/dist/components/micro/collapsible.d.ts +0 -15
  213. package/dist/components/micro/collapsible.d.ts.map +0 -1
  214. package/dist/components/micro/combobox.d.ts +0 -34
  215. package/dist/components/micro/combobox.d.ts.map +0 -1
  216. package/dist/components/micro/command.d.ts +0 -79
  217. package/dist/components/micro/command.d.ts.map +0 -1
  218. package/dist/components/micro/context-menu.d.ts +0 -58
  219. package/dist/components/micro/context-menu.d.ts.map +0 -1
  220. package/dist/components/micro/dialog.d.ts +0 -15
  221. package/dist/components/micro/dialog.d.ts.map +0 -1
  222. package/dist/components/micro/direction.d.ts +0 -2
  223. package/dist/components/micro/direction.d.ts.map +0 -1
  224. package/dist/components/micro/drawer.d.ts +0 -18
  225. package/dist/components/micro/drawer.d.ts.map +0 -1
  226. package/dist/components/micro/dropdown-menu.d.ts +0 -40
  227. package/dist/components/micro/dropdown-menu.d.ts.map +0 -1
  228. package/dist/components/micro/empty.d.ts +0 -30
  229. package/dist/components/micro/empty.d.ts.map +0 -1
  230. package/dist/components/micro/field.d.ts +0 -29
  231. package/dist/components/micro/field.d.ts.map +0 -1
  232. package/dist/components/micro/hover-card.d.ts +0 -18
  233. package/dist/components/micro/hover-card.d.ts.map +0 -1
  234. package/dist/components/micro/input-group.d.ts +0 -17
  235. package/dist/components/micro/input-group.d.ts.map +0 -1
  236. package/dist/components/micro/input-otp.d.ts +0 -44
  237. package/dist/components/micro/input-otp.d.ts.map +0 -1
  238. package/dist/components/micro/input.d.ts +0 -29
  239. package/dist/components/micro/input.d.ts.map +0 -1
  240. package/dist/components/micro/item.d.ts +0 -31
  241. package/dist/components/micro/item.d.ts.map +0 -1
  242. package/dist/components/micro/kbd.d.ts +0 -9
  243. package/dist/components/micro/kbd.d.ts.map +0 -1
  244. package/dist/components/micro/label.d.ts +0 -15
  245. package/dist/components/micro/label.d.ts.map +0 -1
  246. package/dist/components/micro/menubar.d.ts +0 -40
  247. package/dist/components/micro/menubar.d.ts.map +0 -1
  248. package/dist/components/micro/navigation-menu.d.ts +0 -26
  249. package/dist/components/micro/navigation-menu.d.ts.map +0 -1
  250. package/dist/components/micro/pagination.d.ts +0 -33
  251. package/dist/components/micro/pagination.d.ts.map +0 -1
  252. package/dist/components/micro/popover.d.ts +0 -24
  253. package/dist/components/micro/popover.d.ts.map +0 -1
  254. package/dist/components/micro/progress.d.ts +0 -19
  255. package/dist/components/micro/progress.d.ts.map +0 -1
  256. package/dist/components/micro/radio-group.d.ts +0 -13
  257. package/dist/components/micro/radio-group.d.ts.map +0 -1
  258. package/dist/components/micro/resizable.d.ts +0 -12
  259. package/dist/components/micro/resizable.d.ts.map +0 -1
  260. package/dist/components/micro/scroll-area.d.ts +0 -12
  261. package/dist/components/micro/scroll-area.d.ts.map +0 -1
  262. package/dist/components/micro/select.d.ts +0 -22
  263. package/dist/components/micro/select.d.ts.map +0 -1
  264. package/dist/components/micro/separator.d.ts +0 -9
  265. package/dist/components/micro/separator.d.ts.map +0 -1
  266. package/dist/components/micro/sheet.d.ts +0 -17
  267. package/dist/components/micro/sheet.d.ts.map +0 -1
  268. package/dist/components/micro/sidebar.d.ts +0 -28
  269. package/dist/components/micro/sidebar.d.ts.map +0 -1
  270. package/dist/components/micro/skeleton.d.ts +0 -16
  271. package/dist/components/micro/skeleton.d.ts.map +0 -1
  272. package/dist/components/micro/slider.d.ts +0 -21
  273. package/dist/components/micro/slider.d.ts.map +0 -1
  274. package/dist/components/micro/sonner.d.ts +0 -5
  275. package/dist/components/micro/sonner.d.ts.map +0 -1
  276. package/dist/components/micro/spinner.d.ts +0 -21
  277. package/dist/components/micro/spinner.d.ts.map +0 -1
  278. package/dist/components/micro/switch.d.ts +0 -13
  279. package/dist/components/micro/switch.d.ts.map +0 -1
  280. package/dist/components/micro/table.d.ts +0 -17
  281. package/dist/components/micro/table.d.ts.map +0 -1
  282. package/dist/components/micro/tabs.d.ts +0 -13
  283. package/dist/components/micro/tabs.d.ts.map +0 -1
  284. package/dist/components/micro/textarea.d.ts +0 -24
  285. package/dist/components/micro/textarea.d.ts.map +0 -1
  286. package/dist/components/micro/theme-provider.d.ts +0 -76
  287. package/dist/components/micro/theme-provider.d.ts.map +0 -1
  288. package/dist/components/micro/toggle-group.d.ts +0 -22
  289. package/dist/components/micro/toggle-group.d.ts.map +0 -1
  290. package/dist/components/micro/toggle.d.ts +0 -16
  291. package/dist/components/micro/toggle.d.ts.map +0 -1
  292. package/dist/components/micro/tooltip.d.ts +0 -21
  293. package/dist/components/micro/tooltip.d.ts.map +0 -1
  294. package/dist/dev/App.d.ts +0 -3
  295. package/dist/dev/App.d.ts.map +0 -1
  296. package/dist/dev/components/GladvnLogo.d.ts +0 -10
  297. package/dist/dev/components/GladvnLogo.d.ts.map +0 -1
  298. package/dist/dev/components/code-highlighter.d.ts +0 -5
  299. package/dist/dev/components/code-highlighter.d.ts.map +0 -1
  300. package/dist/dev/components/dev-context.d.ts +0 -12
  301. package/dist/dev/components/dev-context.d.ts.map +0 -1
  302. package/dist/dev/components/showcase.d.ts +0 -72
  303. package/dist/dev/components/showcase.d.ts.map +0 -1
  304. package/dist/dev/data.d.ts +0 -68
  305. package/dist/dev/data.d.ts.map +0 -1
  306. package/dist/dev/main.d.ts +0 -1
  307. package/dist/dev/main.d.ts.map +0 -1
  308. package/dist/dev/sections/buttons.d.ts +0 -2
  309. package/dist/dev/sections/buttons.d.ts.map +0 -1
  310. package/dist/dev/sections/display.d.ts +0 -2
  311. package/dist/dev/sections/display.d.ts.map +0 -1
  312. package/dist/dev/sections/feedback.d.ts +0 -2
  313. package/dist/dev/sections/feedback.d.ts.map +0 -1
  314. package/dist/dev/sections/forms.d.ts +0 -2
  315. package/dist/dev/sections/forms.d.ts.map +0 -1
  316. package/dist/dev/sections/interactive.d.ts +0 -2
  317. package/dist/dev/sections/interactive.d.ts.map +0 -1
  318. package/dist/dev/sections/overview.d.ts +0 -2
  319. package/dist/dev/sections/overview.d.ts.map +0 -1
  320. package/dist/dev/showcase/accordion.d.ts +0 -2
  321. package/dist/dev/showcase/accordion.d.ts.map +0 -1
  322. package/dist/dev/showcase/alert-dialog.d.ts +0 -2
  323. package/dist/dev/showcase/alert-dialog.d.ts.map +0 -1
  324. package/dist/dev/showcase/alert.d.ts +0 -2
  325. package/dist/dev/showcase/alert.d.ts.map +0 -1
  326. package/dist/dev/showcase/aspect-ratio.d.ts +0 -2
  327. package/dist/dev/showcase/aspect-ratio.d.ts.map +0 -1
  328. package/dist/dev/showcase/avatar.d.ts +0 -2
  329. package/dist/dev/showcase/avatar.d.ts.map +0 -1
  330. package/dist/dev/showcase/badge.d.ts +0 -2
  331. package/dist/dev/showcase/badge.d.ts.map +0 -1
  332. package/dist/dev/showcase/breadcrumb.d.ts +0 -2
  333. package/dist/dev/showcase/breadcrumb.d.ts.map +0 -1
  334. package/dist/dev/showcase/button.d.ts +0 -2
  335. package/dist/dev/showcase/button.d.ts.map +0 -1
  336. package/dist/dev/showcase/calendar.d.ts +0 -2
  337. package/dist/dev/showcase/calendar.d.ts.map +0 -1
  338. package/dist/dev/showcase/card.d.ts +0 -2
  339. package/dist/dev/showcase/card.d.ts.map +0 -1
  340. package/dist/dev/showcase/carousel.d.ts +0 -2
  341. package/dist/dev/showcase/carousel.d.ts.map +0 -1
  342. package/dist/dev/showcase/chart.d.ts +0 -2
  343. package/dist/dev/showcase/chart.d.ts.map +0 -1
  344. package/dist/dev/showcase/checkbox.d.ts +0 -2
  345. package/dist/dev/showcase/checkbox.d.ts.map +0 -1
  346. package/dist/dev/showcase/collapsible.d.ts +0 -3
  347. package/dist/dev/showcase/collapsible.d.ts.map +0 -1
  348. package/dist/dev/showcase/combobox.d.ts +0 -2
  349. package/dist/dev/showcase/combobox.d.ts.map +0 -1
  350. package/dist/dev/showcase/command.d.ts +0 -2
  351. package/dist/dev/showcase/command.d.ts.map +0 -1
  352. package/dist/dev/showcase/context-menu.d.ts +0 -2
  353. package/dist/dev/showcase/context-menu.d.ts.map +0 -1
  354. package/dist/dev/showcase/dialog.d.ts +0 -2
  355. package/dist/dev/showcase/dialog.d.ts.map +0 -1
  356. package/dist/dev/showcase/drawer.d.ts +0 -2
  357. package/dist/dev/showcase/drawer.d.ts.map +0 -1
  358. package/dist/dev/showcase/dropdown-menu.d.ts +0 -2
  359. package/dist/dev/showcase/dropdown-menu.d.ts.map +0 -1
  360. package/dist/dev/showcase/empty.d.ts +0 -2
  361. package/dist/dev/showcase/empty.d.ts.map +0 -1
  362. package/dist/dev/showcase/hover-card.d.ts +0 -2
  363. package/dist/dev/showcase/hover-card.d.ts.map +0 -1
  364. package/dist/dev/showcase/input-group.d.ts +0 -2
  365. package/dist/dev/showcase/input-group.d.ts.map +0 -1
  366. package/dist/dev/showcase/input-otp.d.ts +0 -2
  367. package/dist/dev/showcase/input-otp.d.ts.map +0 -1
  368. package/dist/dev/showcase/input.d.ts +0 -2
  369. package/dist/dev/showcase/input.d.ts.map +0 -1
  370. package/dist/dev/showcase/item.d.ts +0 -2
  371. package/dist/dev/showcase/item.d.ts.map +0 -1
  372. package/dist/dev/showcase/kbd.d.ts +0 -2
  373. package/dist/dev/showcase/kbd.d.ts.map +0 -1
  374. package/dist/dev/showcase/label.d.ts +0 -2
  375. package/dist/dev/showcase/label.d.ts.map +0 -1
  376. package/dist/dev/showcase/menubar.d.ts +0 -2
  377. package/dist/dev/showcase/menubar.d.ts.map +0 -1
  378. package/dist/dev/showcase/navigation-menu.d.ts +0 -3
  379. package/dist/dev/showcase/navigation-menu.d.ts.map +0 -1
  380. package/dist/dev/showcase/overview.d.ts +0 -2
  381. package/dist/dev/showcase/overview.d.ts.map +0 -1
  382. package/dist/dev/showcase/pagination.d.ts +0 -2
  383. package/dist/dev/showcase/pagination.d.ts.map +0 -1
  384. package/dist/dev/showcase/popover.d.ts +0 -2
  385. package/dist/dev/showcase/popover.d.ts.map +0 -1
  386. package/dist/dev/showcase/progress.d.ts +0 -2
  387. package/dist/dev/showcase/progress.d.ts.map +0 -1
  388. package/dist/dev/showcase/radio-group.d.ts +0 -2
  389. package/dist/dev/showcase/radio-group.d.ts.map +0 -1
  390. package/dist/dev/showcase/resizable.d.ts +0 -2
  391. package/dist/dev/showcase/resizable.d.ts.map +0 -1
  392. package/dist/dev/showcase/scroll-area.d.ts +0 -2
  393. package/dist/dev/showcase/scroll-area.d.ts.map +0 -1
  394. package/dist/dev/showcase/select.d.ts +0 -2
  395. package/dist/dev/showcase/select.d.ts.map +0 -1
  396. package/dist/dev/showcase/separator.d.ts +0 -2
  397. package/dist/dev/showcase/separator.d.ts.map +0 -1
  398. package/dist/dev/showcase/sheet.d.ts +0 -2
  399. package/dist/dev/showcase/sheet.d.ts.map +0 -1
  400. package/dist/dev/showcase/sidebar.d.ts +0 -2
  401. package/dist/dev/showcase/sidebar.d.ts.map +0 -1
  402. package/dist/dev/showcase/skeleton.d.ts +0 -2
  403. package/dist/dev/showcase/skeleton.d.ts.map +0 -1
  404. package/dist/dev/showcase/slider.d.ts +0 -2
  405. package/dist/dev/showcase/slider.d.ts.map +0 -1
  406. package/dist/dev/showcase/sonner.d.ts +0 -2
  407. package/dist/dev/showcase/sonner.d.ts.map +0 -1
  408. package/dist/dev/showcase/spinner.d.ts +0 -2
  409. package/dist/dev/showcase/spinner.d.ts.map +0 -1
  410. package/dist/dev/showcase/switch.d.ts +0 -2
  411. package/dist/dev/showcase/switch.d.ts.map +0 -1
  412. package/dist/dev/showcase/table.d.ts +0 -2
  413. package/dist/dev/showcase/table.d.ts.map +0 -1
  414. package/dist/dev/showcase/tabs.d.ts +0 -2
  415. package/dist/dev/showcase/tabs.d.ts.map +0 -1
  416. package/dist/dev/showcase/textarea.d.ts +0 -2
  417. package/dist/dev/showcase/textarea.d.ts.map +0 -1
  418. package/dist/dev/showcase/toast.d.ts +0 -2
  419. package/dist/dev/showcase/toast.d.ts.map +0 -1
  420. package/dist/dev/showcase/toggle-group.d.ts +0 -2
  421. package/dist/dev/showcase/toggle-group.d.ts.map +0 -1
  422. package/dist/dev/showcase/toggle.d.ts +0 -2
  423. package/dist/dev/showcase/toggle.d.ts.map +0 -1
  424. package/dist/dev/showcase/tooltip.d.ts +0 -2
  425. package/dist/dev/showcase/tooltip.d.ts.map +0 -1
  426. package/dist/hooks/use-controllable-state.d.ts +0 -14
  427. package/dist/hooks/use-controllable-state.d.ts.map +0 -1
  428. package/dist/hooks/use-mobile.d.ts +0 -2
  429. package/dist/hooks/use-mobile.d.ts.map +0 -1
  430. package/dist/index.cjs +0 -5099
  431. package/dist/index.cjs.map +0 -1
  432. package/dist/index.d.ts +0 -58
  433. package/dist/index.d.ts.map +0 -1
  434. package/dist/index.js +0 -4753
  435. package/dist/index.js.map +0 -1
  436. package/dist/lib/types.d.ts +0 -4
  437. package/dist/lib/types.d.ts.map +0 -1
  438. package/dist/lib/utils.d.ts +0 -3
  439. package/dist/lib/utils.d.ts.map +0 -1
  440. package/dist/preset.d.ts +0 -18
  441. package/dist/preset.d.ts.map +0 -1
  442. package/dist/test/setup.d.ts +0 -1
  443. package/dist/test/setup.d.ts.map +0 -1
  444. package/scripts/add-icononly-prop.ts +0 -84
  445. package/scripts/audit-best-practices.ts +0 -114
  446. package/scripts/audit-showcase.ts +0 -262
  447. package/scripts/audit-showcases.ts +0 -83
  448. package/scripts/clean-imports.ts +0 -21
  449. package/scripts/count_missing.ts +0 -24
  450. package/scripts/find-css-vars.ts +0 -62
  451. package/scripts/fix-portals.ts +0 -90
  452. package/scripts/format-codestrings.ts +0 -87
  453. package/scripts/full-audit.ts +0 -89
  454. package/scripts/merge-components.cjs +0 -65
  455. package/scripts/merge-components.js +0 -64
  456. package/scripts/optimize-barrel.ts +0 -116
  457. package/scripts/organize-imports.ts +0 -21
  458. package/scripts/refactor_divs.ts +0 -39
  459. package/scripts/regex-format.cjs +0 -67
  460. package/scripts/remove_div_wrappers.ts +0 -17
  461. package/scripts/tmp.tsx +0 -25
  462. package/scripts/update-gaps.ts +0 -83
  463. package/scripts/update_showcase_codestrings.ts +0 -87
@@ -0,0 +1,127 @@
1
+
2
+ import { render, screen, waitFor } from "@testing-library/react";
3
+ import userEvent from "@testing-library/user-event";
4
+ import { describe, expect, it } from "vitest";
5
+
6
+ import {
7
+ Dialog,
8
+ DialogClose,
9
+ DialogContent,
10
+ DialogDescription,
11
+ DialogFooter,
12
+ DialogHeader,
13
+ DialogTitle,
14
+ DialogTrigger,
15
+ } from "./dialog";
16
+
17
+ describe("Dialog", () => {
18
+ it("[3C.4-01] [P1] renders trigger correctly and content is hidden initially", () => {
19
+ // Given
20
+ render(
21
+ <Dialog>
22
+ <DialogTrigger>Open Dialog</DialogTrigger>
23
+ <DialogContent>
24
+ <DialogHeader>
25
+ <DialogTitle>Dialog Title</DialogTitle>
26
+ <DialogDescription>Dialog description</DialogDescription>
27
+ </DialogHeader>
28
+ </DialogContent>
29
+ </Dialog>,
30
+ );
31
+
32
+ const trigger = screen.getByRole("button", { name: "Open Dialog" });
33
+ // Then
34
+ expect(trigger).toBeInTheDocument();
35
+
36
+ // Content should not be in the document
37
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
38
+ });
39
+
40
+ it("[3C.4-02] [P1] opens the dialog when trigger is clicked", async () => {
41
+ // Given
42
+ const user = userEvent.setup();
43
+ render(
44
+ <Dialog>
45
+ <DialogTrigger>Open Dialog</DialogTrigger>
46
+ <DialogContent>
47
+ <DialogHeader>
48
+ <DialogTitle>Dialog Title</DialogTitle>
49
+ <DialogDescription>Dialog description</DialogDescription>
50
+ </DialogHeader>
51
+ <DialogFooter>
52
+ <DialogClose>Close</DialogClose>
53
+ </DialogFooter>
54
+ </DialogContent>
55
+ </Dialog>,
56
+ );
57
+
58
+ const trigger = screen.getByRole("button", { name: "Open Dialog" });
59
+ // When
60
+ await user.click(trigger);
61
+
62
+ // Then
63
+ await waitFor(() => {
64
+ const dialog = screen.getByRole("dialog");
65
+ expect(dialog).toBeInTheDocument();
66
+ expect(screen.getByText("Dialog Title")).toBeInTheDocument();
67
+ expect(screen.getByText("Dialog description")).toBeInTheDocument();
68
+ });
69
+ });
70
+
71
+ it("[3C.4-03] [P1] closes the dialog when Close button is clicked", async () => {
72
+ // Given
73
+ const user = userEvent.setup();
74
+ render(
75
+ <Dialog>
76
+ <DialogTrigger>Open Dialog</DialogTrigger>
77
+ <DialogContent>
78
+ <DialogTitle>Dialog Title</DialogTitle>
79
+ <DialogClose>Close Me</DialogClose>
80
+ </DialogContent>
81
+ </Dialog>,
82
+ );
83
+
84
+ // Open
85
+ // When
86
+ await user.click(screen.getByRole("button", { name: "Open Dialog" }));
87
+
88
+ // Then
89
+ await waitFor(() => {
90
+ expect(screen.getByRole("dialog")).toBeInTheDocument();
91
+ });
92
+
93
+ // Close
94
+ await user.click(screen.getByRole("button", { name: "Close Me" }));
95
+
96
+ await waitFor(() => {
97
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
98
+ });
99
+ });
100
+
101
+ it("[3C.4-04] [P1] closes the dialog when Escape is pressed", async () => {
102
+ // Given
103
+ const user = userEvent.setup();
104
+ render(
105
+ <Dialog>
106
+ <DialogTrigger>Open Dialog</DialogTrigger>
107
+ <DialogContent>
108
+ <DialogTitle>Dialog Title</DialogTitle>
109
+ </DialogContent>
110
+ </Dialog>,
111
+ );
112
+
113
+ // When
114
+ await user.click(screen.getByRole("button", { name: "Open Dialog" }));
115
+
116
+ // Then
117
+ await waitFor(() => {
118
+ expect(screen.getByRole("dialog")).toBeInTheDocument();
119
+ });
120
+
121
+ await user.keyboard("[Escape]");
122
+
123
+ await waitFor(() => {
124
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
125
+ });
126
+ });
127
+ });
@@ -144,5 +144,5 @@ export {
144
144
  DialogHeader,
145
145
  DialogOverlay,
146
146
  DialogTitle,
147
- DialogTrigger,
147
+ DialogTrigger
148
148
  };
@@ -9,5 +9,5 @@
9
9
 
10
10
  export {
11
11
  DirectionProvider,
12
- useDirection,
12
+ useDirection
13
13
  } from "@base-ui/react/direction-provider";
@@ -10,7 +10,7 @@
10
10
  import * as React from "react";
11
11
 
12
12
  // Fix TS2883: The inferred type cannot be named without a reference to @radix-ui/react-dialog
13
- import type {} from "@radix-ui/react-dialog";
13
+ import type { } from "@radix-ui/react-dialog";
14
14
  import { Drawer as DrawerPrimitive } from "vaul";
15
15
 
16
16
  import { cn } from "../../lib/utils";
@@ -150,5 +150,5 @@ export {
150
150
  DrawerHeader,
151
151
  DrawerOverlay,
152
152
  DrawerTitle,
153
- DrawerTrigger,
153
+ DrawerTrigger
154
154
  };
@@ -0,0 +1,132 @@
1
+
2
+ import { render, screen, waitFor } from "@testing-library/react";
3
+ import userEvent from "@testing-library/user-event";
4
+ import { describe, expect, it } from "vitest";
5
+
6
+ import {
7
+ DropdownMenu,
8
+ DropdownMenuContent,
9
+ DropdownMenuGroup,
10
+ DropdownMenuItem,
11
+ DropdownMenuLabel,
12
+ DropdownMenuSeparator,
13
+ DropdownMenuTrigger,
14
+ } from "./dropdown-menu";
15
+
16
+ describe("DropdownMenu", () => {
17
+ it("[3C.5-01] [P1] renders trigger correctly and content is hidden initially", () => {
18
+ // Given
19
+ render(
20
+ <DropdownMenu>
21
+ <DropdownMenuTrigger>Open Menu</DropdownMenuTrigger>
22
+ <DropdownMenuContent>
23
+ <DropdownMenuGroup>
24
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
25
+ </DropdownMenuGroup>
26
+ <DropdownMenuSeparator />
27
+ <DropdownMenuItem>Profile</DropdownMenuItem>
28
+ <DropdownMenuItem>Settings</DropdownMenuItem>
29
+ </DropdownMenuContent>
30
+ </DropdownMenu>,
31
+ );
32
+
33
+ const trigger = screen.getByRole("button", { name: "Open Menu" });
34
+ // Then
35
+ expect(trigger).toBeInTheDocument();
36
+
37
+ // Base UI Menu might not use role="dialog" or "menu" before open, but it's hidden
38
+ expect(screen.queryByRole("menu")).not.toBeInTheDocument();
39
+ });
40
+
41
+ it("[3C.5-02] [P1] opens the menu when trigger is clicked", async () => {
42
+ // Given
43
+ const user = userEvent.setup();
44
+ render(
45
+ <DropdownMenu>
46
+ <DropdownMenuTrigger>Open Menu</DropdownMenuTrigger>
47
+ <DropdownMenuContent>
48
+ <DropdownMenuGroup>
49
+ <DropdownMenuLabel>My Account</DropdownMenuLabel>
50
+ </DropdownMenuGroup>
51
+ <DropdownMenuItem>Profile</DropdownMenuItem>
52
+ </DropdownMenuContent>
53
+ </DropdownMenu>,
54
+ );
55
+
56
+ const trigger = screen.getByRole("button", { name: "Open Menu" });
57
+ // When
58
+ await user.click(trigger);
59
+
60
+ // Then
61
+ await waitFor(() => {
62
+ const menu = screen.getByRole("menu");
63
+ expect(menu).toBeInTheDocument();
64
+ expect(screen.getByText("My Account")).toBeInTheDocument();
65
+ expect(
66
+ screen.getByRole("menuitem", { name: "Profile" }),
67
+ ).toBeInTheDocument();
68
+ });
69
+ });
70
+
71
+ it("[3C.5-03] [P1] closes the menu when an item is clicked", async () => {
72
+ // Given
73
+ const user = userEvent.setup();
74
+ render(
75
+ <DropdownMenu>
76
+ <DropdownMenuTrigger>Open Menu</DropdownMenuTrigger>
77
+ <DropdownMenuContent>
78
+ <DropdownMenuItem>Profile</DropdownMenuItem>
79
+ </DropdownMenuContent>
80
+ </DropdownMenu>,
81
+ );
82
+
83
+ // When
84
+ await user.click(screen.getByRole("button", { name: "Open Menu" }));
85
+
86
+ // Then
87
+ await waitFor(() => {
88
+ expect(screen.getByRole("menu")).toBeInTheDocument();
89
+ });
90
+
91
+ const menuItem = screen.getByRole("menuitem", { name: "Profile" });
92
+ await user.click(menuItem);
93
+
94
+ await waitFor(() => {
95
+ expect(screen.queryByRole("menu")).not.toBeInTheDocument();
96
+ });
97
+ });
98
+
99
+ it("[3C.5-04] [P1] supports keyboard navigation (ArrowDown, Escape)", async () => {
100
+ // Given
101
+ const user = userEvent.setup();
102
+ render(
103
+ <DropdownMenu>
104
+ <DropdownMenuTrigger>Open Menu</DropdownMenuTrigger>
105
+ <DropdownMenuContent>
106
+ <DropdownMenuItem>Profile</DropdownMenuItem>
107
+ <DropdownMenuItem>Settings</DropdownMenuItem>
108
+ </DropdownMenuContent>
109
+ </DropdownMenu>,
110
+ );
111
+
112
+ const trigger = screen.getByRole("button", { name: "Open Menu" });
113
+ // When
114
+ await user.tab();
115
+ // Then
116
+ expect(trigger).toHaveFocus();
117
+
118
+ // Open with ArrowDown or Enter
119
+ await user.keyboard("[Enter]");
120
+
121
+ await waitFor(() => {
122
+ expect(screen.getByRole("menu")).toBeInTheDocument();
123
+ });
124
+
125
+ // Close with Escape
126
+ await user.keyboard("[Escape]");
127
+
128
+ await waitFor(() => {
129
+ expect(screen.queryByRole("menu")).not.toBeInTheDocument();
130
+ });
131
+ });
132
+ });
@@ -307,5 +307,5 @@ export {
307
307
  DropdownMenuSub,
308
308
  DropdownMenuSubContent,
309
309
  DropdownMenuSubTrigger,
310
- DropdownMenuTrigger,
310
+ DropdownMenuTrigger
311
311
  };
@@ -141,5 +141,5 @@ export {
141
141
  EmptyDescription,
142
142
  EmptyHeader,
143
143
  EmptyMedia,
144
- EmptyTitle,
144
+ EmptyTitle
145
145
  };
@@ -308,5 +308,5 @@ export {
308
308
  FieldLegend,
309
309
  FieldSeparator,
310
310
  FieldSet,
311
- FieldTitle,
311
+ FieldTitle
312
312
  };
@@ -266,5 +266,5 @@ export {
266
266
  InputGroupButton,
267
267
  InputGroupInput,
268
268
  InputGroupText,
269
- InputGroupTextarea,
269
+ InputGroupTextarea
270
270
  };
@@ -0,0 +1,95 @@
1
+ import * as React from "react";
2
+
3
+ import { render, screen } from "@testing-library/react";
4
+ import userEvent from "@testing-library/user-event";
5
+ import { describe, expect, it, vi } from "vitest";
6
+
7
+ import { Input } from "./input";
8
+
9
+ describe("Input", () => {
10
+ // 1. Rendering & Attributes (API Surface)
11
+ it("[3C.2-01] [P1] renders correctly with default props", () => {
12
+ // Given
13
+ render(<Input placeholder="Enter email" />);
14
+ const input = screen.getByPlaceholderText("Enter email");
15
+ // Then
16
+ expect(input).toBeInTheDocument();
17
+ expect(input.tagName).toBe("INPUT");
18
+ expect(input).toHaveAttribute("data-slot", "input");
19
+ });
20
+
21
+ it("[3C.2-02] [P1] applies sizing correctly", () => {
22
+ // Given
23
+ render(<Input placeholder="Small input" size="sm" />);
24
+ const input = screen.getByPlaceholderText("Small input");
25
+ // We check the merged class string instead of exact match to avoid fragility,
26
+ // but a basic check that it received the size classes is fine.
27
+ // The cva variant for sm contains "h-7"
28
+ // Then
29
+ expect(input.className).toContain("h-7");
30
+ });
31
+
32
+ it("[3C.2-03] [P1] merges custom classNames properly", () => {
33
+ // Given
34
+ render(<Input placeholder="Classy input" className="custom-test-class" />);
35
+ const input = screen.getByPlaceholderText("Classy input");
36
+ // Then
37
+ expect(input).toHaveClass("custom-test-class");
38
+ });
39
+
40
+ // 2. Behaviors (Interaction & Events)
41
+ it("[3C.2-04] [P1] handles user typing correctly", async () => {
42
+ // Given
43
+ const user = userEvent.setup();
44
+ const handleChange = vi.fn();
45
+ render(<Input placeholder="Type here" onChange={handleChange} />);
46
+
47
+ const input = screen.getByPlaceholderText("Type here");
48
+ // When
49
+ await user.type(input, "Hello");
50
+
51
+ // Then
52
+ expect(input).toHaveValue("Hello");
53
+ expect(handleChange).toHaveBeenCalled();
54
+ });
55
+
56
+ it("[3C.2-05] [P1] can be focused and activated via keyboard", async () => {
57
+ // Given
58
+ const user = userEvent.setup();
59
+ render(<Input placeholder="Focus me" />);
60
+
61
+ const input = screen.getByPlaceholderText("Focus me");
62
+
63
+ // Test focus
64
+ // When
65
+ await user.tab();
66
+ // Then
67
+ expect(input).toHaveFocus();
68
+ });
69
+
70
+ it("[3C.2-06] [P1] handles disabled state correctly and blocks typing", async () => {
71
+ // Given
72
+ const user = userEvent.setup();
73
+ render(<Input placeholder="Disabled" disabled />);
74
+
75
+ const input = screen.getByPlaceholderText("Disabled");
76
+ // Then
77
+ expect(input).toBeDisabled();
78
+
79
+ // When
80
+ await user.type(input, "Hello");
81
+ expect(input).toHaveValue("");
82
+ });
83
+
84
+ // 3. Architecture & Integration
85
+ it("[3C.2-07] [P1] forwards the ref to the underlying DOM element", () => {
86
+ // Given
87
+ const ref = React.createRef<HTMLInputElement>();
88
+ render(
89
+ <Input ref={ref} placeholder="Ref input" defaultValue="ref value" />,
90
+ );
91
+ // Then
92
+ expect(ref.current).toBeInstanceOf(HTMLInputElement);
93
+ expect(ref.current?.value).toBe("ref value");
94
+ });
95
+ });
@@ -203,5 +203,5 @@ export {
203
203
  ItemHeader,
204
204
  ItemMedia,
205
205
  ItemSeparator,
206
- ItemTitle,
206
+ ItemTitle
207
207
  };
@@ -291,5 +291,5 @@ export {
291
291
  MenubarSub,
292
292
  MenubarSubContent,
293
293
  MenubarSubTrigger,
294
- MenubarTrigger,
294
+ MenubarTrigger
295
295
  };
@@ -201,5 +201,5 @@ export {
201
201
  NavigationMenuPositioner,
202
202
  NavigationMenuTrigger,
203
203
  navigationMenuTriggerStyle,
204
- NavigationMenuViewport,
204
+ NavigationMenuViewport
205
205
  };
@@ -159,5 +159,5 @@ export {
159
159
  PaginationItem,
160
160
  PaginationLink,
161
161
  PaginationNext,
162
- PaginationPrevious,
162
+ PaginationPrevious
163
163
  };
@@ -0,0 +1,83 @@
1
+
2
+ import { render, screen, waitFor } from "@testing-library/react";
3
+ import userEvent from "@testing-library/user-event";
4
+ import { describe, expect, it } from "vitest";
5
+
6
+ import {
7
+ Popover,
8
+ PopoverContent,
9
+ PopoverDescription,
10
+ PopoverTitle,
11
+ PopoverTrigger,
12
+ } from "./popover";
13
+
14
+ describe("Popover", () => {
15
+ it("[3C.14-01] [P1] renders trigger correctly and content is hidden initially", () => {
16
+ // Given
17
+ render(
18
+ <Popover>
19
+ <PopoverTrigger>Open Popover</PopoverTrigger>
20
+ <PopoverContent>
21
+ <PopoverTitle>Popover Title</PopoverTitle>
22
+ <PopoverDescription>Popover Description</PopoverDescription>
23
+ </PopoverContent>
24
+ </Popover>,
25
+ );
26
+
27
+ const trigger = screen.getByRole("button", { name: "Open Popover" });
28
+ // Then
29
+ expect(trigger).toBeInTheDocument();
30
+
31
+ // Content should not be in the document
32
+ expect(screen.queryByText("Popover Title")).not.toBeInTheDocument();
33
+ });
34
+
35
+ it("[3C.14-02] [P1] opens the popover when trigger is clicked", async () => {
36
+ // Given
37
+ const user = userEvent.setup();
38
+ render(
39
+ <Popover>
40
+ <PopoverTrigger>Open Popover</PopoverTrigger>
41
+ <PopoverContent>
42
+ <PopoverTitle>Popover Title</PopoverTitle>
43
+ </PopoverContent>
44
+ </Popover>,
45
+ );
46
+
47
+ const trigger = screen.getByRole("button", { name: "Open Popover" });
48
+ // When
49
+ await user.click(trigger);
50
+
51
+ // Then
52
+ await waitFor(() => {
53
+ expect(screen.getByText("Popover Title")).toBeInTheDocument();
54
+ });
55
+ });
56
+
57
+ it("[3C.14-03] [P1] closes the popover when Escape is pressed", async () => {
58
+ // Given
59
+ const user = userEvent.setup();
60
+ render(
61
+ <Popover>
62
+ <PopoverTrigger>Open Popover</PopoverTrigger>
63
+ <PopoverContent>
64
+ <PopoverTitle>Popover Title</PopoverTitle>
65
+ </PopoverContent>
66
+ </Popover>,
67
+ );
68
+
69
+ // When
70
+ await user.click(screen.getByRole("button", { name: "Open Popover" }));
71
+
72
+ // Then
73
+ await waitFor(() => {
74
+ expect(screen.getByText("Popover Title")).toBeInTheDocument();
75
+ });
76
+
77
+ await user.keyboard("[Escape]");
78
+
79
+ await waitFor(() => {
80
+ expect(screen.queryByText("Popover Title")).not.toBeInTheDocument();
81
+ });
82
+ });
83
+ });
@@ -134,5 +134,5 @@ export {
134
134
  PopoverDescription,
135
135
  PopoverHeader,
136
136
  PopoverTitle,
137
- PopoverTrigger,
137
+ PopoverTrigger
138
138
  };
@@ -141,5 +141,5 @@ export {
141
141
  ProgressIndicator,
142
142
  ProgressLabel,
143
143
  ProgressTrack,
144
- ProgressValue,
144
+ ProgressValue
145
145
  };
@@ -0,0 +1,122 @@
1
+ import * as React from "react";
2
+
3
+ import { render, screen, waitFor } from "@testing-library/react";
4
+ import userEvent from "@testing-library/user-event";
5
+ import { describe, expect, it } from "vitest";
6
+
7
+ import {
8
+ Select,
9
+ SelectContent,
10
+ SelectItem,
11
+ SelectTrigger,
12
+ SelectValue,
13
+ } from "./select";
14
+
15
+ describe("Select", () => {
16
+ it("[3C.3-01] [P1] renders correctly with default closed state", () => {
17
+ // Given
18
+ render(
19
+ <Select>
20
+ <SelectTrigger aria-label="Food">
21
+ <SelectValue placeholder="Select a fruit" />
22
+ </SelectTrigger>
23
+ <SelectContent>
24
+ <SelectItem value="apple">Apple</SelectItem>
25
+ <SelectItem value="banana">Banana</SelectItem>
26
+ </SelectContent>
27
+ </Select>,
28
+ );
29
+
30
+ // The trigger should be visible
31
+ const trigger = screen.getByRole("combobox", { name: "Food" });
32
+ // Then
33
+ expect(trigger).toBeInTheDocument();
34
+
35
+ // Check placeholder
36
+ expect(trigger).toHaveTextContent("Select a fruit");
37
+
38
+ // The popup content should not be in the document initially
39
+ expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
40
+ });
41
+
42
+ it("[3C.3-02] [P1] opens the popup on click and allows selection", async () => {
43
+ // Given
44
+ const user = userEvent.setup();
45
+
46
+ const ControlledSelect = () => {
47
+ const [val, setVal] = React.useState<string | null>("apple");
48
+ return (
49
+ <Select value={val} onValueChange={setVal}>
50
+ <SelectTrigger aria-label="Food">
51
+ <SelectValue placeholder="Select a fruit" />
52
+ </SelectTrigger>
53
+ <SelectContent>
54
+ <SelectItem value="apple">Apple</SelectItem>
55
+ <SelectItem value="banana">Banana</SelectItem>
56
+ </SelectContent>
57
+ </Select>
58
+ );
59
+ };
60
+
61
+ render(<ControlledSelect />);
62
+
63
+ const trigger = screen.getByRole("combobox", { name: "Food" });
64
+
65
+ // Click trigger to open
66
+ // When
67
+ await user.click(trigger);
68
+
69
+ // Wait for the popup to appear in the document
70
+ // Then
71
+ await waitFor(() => {
72
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
73
+ });
74
+
75
+ // Select Banana
76
+ const bananaItem = screen.getByRole("option", { name: "Banana" });
77
+ await user.click(bananaItem);
78
+
79
+ // Wait for the trigger to update
80
+ await waitFor(() => {
81
+ expect(trigger).toHaveTextContent(/banana/i);
82
+ });
83
+ });
84
+
85
+ it("[3C.3-03] [P1] can be navigated via keyboard", async () => {
86
+ // Given
87
+ const user = userEvent.setup();
88
+ render(
89
+ <Select defaultValue="apple">
90
+ <SelectTrigger aria-label="Food">
91
+ <SelectValue placeholder="Select a fruit" />
92
+ </SelectTrigger>
93
+ <SelectContent>
94
+ <SelectItem value="apple">Apple</SelectItem>
95
+ <SelectItem value="banana">Banana</SelectItem>
96
+ </SelectContent>
97
+ </Select>,
98
+ );
99
+
100
+ const trigger = screen.getByRole("combobox", { name: "Food" });
101
+
102
+ // Focus trigger
103
+ // When
104
+ await user.tab();
105
+ // Then
106
+ expect(trigger).toHaveFocus();
107
+
108
+ // Open menu with Enter (or Space)
109
+ await user.keyboard("[Enter]");
110
+
111
+ await waitFor(() => {
112
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
113
+ });
114
+
115
+ // Pressing Escape should close it
116
+ await user.keyboard("[Escape]");
117
+
118
+ await waitFor(() => {
119
+ expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
120
+ });
121
+ });
122
+ });
@@ -238,5 +238,5 @@ export {
238
238
  SelectSeparator,
239
239
  SelectTrigger,
240
240
  SelectValue,
241
- selectTriggerVariants,
241
+ selectTriggerVariants
242
242
  };