gladvn 0.2.14

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 (500) hide show
  1. package/README.md +112 -0
  2. package/bin/cli.js +326 -0
  3. package/dist/components/macro/accordion-preset.d.ts +14 -0
  4. package/dist/components/macro/accordion-preset.d.ts.map +1 -0
  5. package/dist/components/macro/alert-dialog-preset.d.ts +26 -0
  6. package/dist/components/macro/alert-dialog-preset.d.ts.map +1 -0
  7. package/dist/components/macro/alert-preset.d.ts +14 -0
  8. package/dist/components/macro/alert-preset.d.ts.map +1 -0
  9. package/dist/components/macro/avatar-preset.d.ts +11 -0
  10. package/dist/components/macro/avatar-preset.d.ts.map +1 -0
  11. package/dist/components/macro/breadcrumb-preset.d.ts +12 -0
  12. package/dist/components/macro/breadcrumb-preset.d.ts.map +1 -0
  13. package/dist/components/macro/card-preset.d.ts +10 -0
  14. package/dist/components/macro/card-preset.d.ts.map +1 -0
  15. package/dist/components/macro/carousel-preset.d.ts +18 -0
  16. package/dist/components/macro/carousel-preset.d.ts.map +1 -0
  17. package/dist/components/macro/checkbox-preset.d.ts +14 -0
  18. package/dist/components/macro/checkbox-preset.d.ts.map +1 -0
  19. package/dist/components/macro/combobox-preset.d.ts +27 -0
  20. package/dist/components/macro/combobox-preset.d.ts.map +1 -0
  21. package/dist/components/macro/command-preset.d.ts +16 -0
  22. package/dist/components/macro/command-preset.d.ts.map +1 -0
  23. package/dist/components/macro/date-picker.d.ts +62 -0
  24. package/dist/components/macro/date-picker.d.ts.map +1 -0
  25. package/dist/components/macro/dialog-preset.d.ts +24 -0
  26. package/dist/components/macro/dialog-preset.d.ts.map +1 -0
  27. package/dist/components/macro/empty-preset.d.ts +15 -0
  28. package/dist/components/macro/empty-preset.d.ts.map +1 -0
  29. package/dist/components/macro/field-preset.d.ts +15 -0
  30. package/dist/components/macro/field-preset.d.ts.map +1 -0
  31. package/dist/components/macro/index.d.ts +22 -0
  32. package/dist/components/macro/index.d.ts.map +1 -0
  33. package/dist/components/macro/input-otp-preset.d.ts +13 -0
  34. package/dist/components/macro/input-otp-preset.d.ts.map +1 -0
  35. package/dist/components/macro/input-preset.d.ts +21 -0
  36. package/dist/components/macro/input-preset.d.ts.map +1 -0
  37. package/dist/components/macro/pagination-preset.d.ts +13 -0
  38. package/dist/components/macro/pagination-preset.d.ts.map +1 -0
  39. package/dist/components/macro/progress-preset.d.ts +10 -0
  40. package/dist/components/macro/progress-preset.d.ts.map +1 -0
  41. package/dist/components/macro/radio-group-preset.d.ts +22 -0
  42. package/dist/components/macro/radio-group-preset.d.ts.map +1 -0
  43. package/dist/components/macro/select-preset.d.ts +42 -0
  44. package/dist/components/macro/select-preset.d.ts.map +1 -0
  45. package/dist/components/macro/slider-preset.d.ts +12 -0
  46. package/dist/components/macro/slider-preset.d.ts.map +1 -0
  47. package/dist/components/macro/switch-preset.d.ts +12 -0
  48. package/dist/components/macro/switch-preset.d.ts.map +1 -0
  49. package/dist/components/macro/tabs-preset.d.ts +17 -0
  50. package/dist/components/macro/tabs-preset.d.ts.map +1 -0
  51. package/dist/components/macro/textarea-preset.d.ts +17 -0
  52. package/dist/components/macro/textarea-preset.d.ts.map +1 -0
  53. package/dist/components/micro/accordion.d.ts +8 -0
  54. package/dist/components/micro/accordion.d.ts.map +1 -0
  55. package/dist/components/micro/alert-dialog.d.ts +33 -0
  56. package/dist/components/micro/alert-dialog.d.ts.map +1 -0
  57. package/dist/components/micro/alert.d.ts +28 -0
  58. package/dist/components/micro/alert.d.ts.map +1 -0
  59. package/dist/components/micro/aspect-ratio.d.ts +13 -0
  60. package/dist/components/micro/aspect-ratio.d.ts.map +1 -0
  61. package/dist/components/micro/avatar.d.ts +23 -0
  62. package/dist/components/micro/avatar.d.ts.map +1 -0
  63. package/dist/components/micro/badge.d.ts +16 -0
  64. package/dist/components/micro/badge.d.ts.map +1 -0
  65. package/dist/components/micro/breadcrumb.d.ts +24 -0
  66. package/dist/components/micro/breadcrumb.d.ts.map +1 -0
  67. package/dist/components/micro/button.d.ts +39 -0
  68. package/dist/components/micro/button.d.ts.map +1 -0
  69. package/dist/components/micro/calendar.d.ts +28 -0
  70. package/dist/components/micro/calendar.d.ts.map +1 -0
  71. package/dist/components/micro/card.d.ts +28 -0
  72. package/dist/components/micro/card.d.ts.map +1 -0
  73. package/dist/components/micro/carousel.d.ts +29 -0
  74. package/dist/components/micro/carousel.d.ts.map +1 -0
  75. package/dist/components/micro/chart.d.ts +49 -0
  76. package/dist/components/micro/chart.d.ts.map +1 -0
  77. package/dist/components/micro/checkbox.d.ts +17 -0
  78. package/dist/components/micro/checkbox.d.ts.map +1 -0
  79. package/dist/components/micro/collapsible.d.ts +15 -0
  80. package/dist/components/micro/collapsible.d.ts.map +1 -0
  81. package/dist/components/micro/combobox.d.ts +33 -0
  82. package/dist/components/micro/combobox.d.ts.map +1 -0
  83. package/dist/components/micro/command.d.ts +79 -0
  84. package/dist/components/micro/command.d.ts.map +1 -0
  85. package/dist/components/micro/context-menu.d.ts +60 -0
  86. package/dist/components/micro/context-menu.d.ts.map +1 -0
  87. package/dist/components/micro/dialog.d.ts +14 -0
  88. package/dist/components/micro/dialog.d.ts.map +1 -0
  89. package/dist/components/micro/direction.d.ts +2 -0
  90. package/dist/components/micro/direction.d.ts.map +1 -0
  91. package/dist/components/micro/drawer.d.ts +17 -0
  92. package/dist/components/micro/drawer.d.ts.map +1 -0
  93. package/dist/components/micro/dropdown-menu.d.ts +37 -0
  94. package/dist/components/micro/dropdown-menu.d.ts.map +1 -0
  95. package/dist/components/micro/empty.d.ts +23 -0
  96. package/dist/components/micro/empty.d.ts.map +1 -0
  97. package/dist/components/micro/field.d.ts +29 -0
  98. package/dist/components/micro/field.d.ts.map +1 -0
  99. package/dist/components/micro/hover-card.d.ts +17 -0
  100. package/dist/components/micro/hover-card.d.ts.map +1 -0
  101. package/dist/components/micro/input-group.d.ts +17 -0
  102. package/dist/components/micro/input-group.d.ts.map +1 -0
  103. package/dist/components/micro/input-otp.d.ts +44 -0
  104. package/dist/components/micro/input-otp.d.ts.map +1 -0
  105. package/dist/components/micro/input.d.ts +22 -0
  106. package/dist/components/micro/input.d.ts.map +1 -0
  107. package/dist/components/micro/item.d.ts +31 -0
  108. package/dist/components/micro/item.d.ts.map +1 -0
  109. package/dist/components/micro/kbd.d.ts +9 -0
  110. package/dist/components/micro/kbd.d.ts.map +1 -0
  111. package/dist/components/micro/label.d.ts +15 -0
  112. package/dist/components/micro/label.d.ts.map +1 -0
  113. package/dist/components/micro/menubar.d.ts +41 -0
  114. package/dist/components/micro/menubar.d.ts.map +1 -0
  115. package/dist/components/micro/navigation-menu.d.ts +18 -0
  116. package/dist/components/micro/navigation-menu.d.ts.map +1 -0
  117. package/dist/components/micro/pagination.d.ts +33 -0
  118. package/dist/components/micro/pagination.d.ts.map +1 -0
  119. package/dist/components/micro/popover.d.ts +23 -0
  120. package/dist/components/micro/popover.d.ts.map +1 -0
  121. package/dist/components/micro/progress.d.ts +19 -0
  122. package/dist/components/micro/progress.d.ts.map +1 -0
  123. package/dist/components/micro/radio-group.d.ts +13 -0
  124. package/dist/components/micro/radio-group.d.ts.map +1 -0
  125. package/dist/components/micro/resizable.d.ts +12 -0
  126. package/dist/components/micro/resizable.d.ts.map +1 -0
  127. package/dist/components/micro/scroll-area.d.ts +12 -0
  128. package/dist/components/micro/scroll-area.d.ts.map +1 -0
  129. package/dist/components/micro/select.d.ts +21 -0
  130. package/dist/components/micro/select.d.ts.map +1 -0
  131. package/dist/components/micro/separator.d.ts +9 -0
  132. package/dist/components/micro/separator.d.ts.map +1 -0
  133. package/dist/components/micro/sheet.d.ts +17 -0
  134. package/dist/components/micro/sheet.d.ts.map +1 -0
  135. package/dist/components/micro/sidebar.d.ts +28 -0
  136. package/dist/components/micro/sidebar.d.ts.map +1 -0
  137. package/dist/components/micro/skeleton.d.ts +9 -0
  138. package/dist/components/micro/skeleton.d.ts.map +1 -0
  139. package/dist/components/micro/slider.d.ts +14 -0
  140. package/dist/components/micro/slider.d.ts.map +1 -0
  141. package/dist/components/micro/sonner.d.ts +5 -0
  142. package/dist/components/micro/sonner.d.ts.map +1 -0
  143. package/dist/components/micro/spinner.d.ts +21 -0
  144. package/dist/components/micro/spinner.d.ts.map +1 -0
  145. package/dist/components/micro/switch.d.ts +13 -0
  146. package/dist/components/micro/switch.d.ts.map +1 -0
  147. package/dist/components/micro/table.d.ts +17 -0
  148. package/dist/components/micro/table.d.ts.map +1 -0
  149. package/dist/components/micro/tabs.d.ts +13 -0
  150. package/dist/components/micro/tabs.d.ts.map +1 -0
  151. package/dist/components/micro/textarea.d.ts +17 -0
  152. package/dist/components/micro/textarea.d.ts.map +1 -0
  153. package/dist/components/micro/theme-provider.d.ts +76 -0
  154. package/dist/components/micro/theme-provider.d.ts.map +1 -0
  155. package/dist/components/micro/toggle-group.d.ts +22 -0
  156. package/dist/components/micro/toggle-group.d.ts.map +1 -0
  157. package/dist/components/micro/toggle.d.ts +16 -0
  158. package/dist/components/micro/toggle.d.ts.map +1 -0
  159. package/dist/components/micro/tooltip.d.ts +20 -0
  160. package/dist/components/micro/tooltip.d.ts.map +1 -0
  161. package/dist/dev/App.d.ts +3 -0
  162. package/dist/dev/App.d.ts.map +1 -0
  163. package/dist/dev/components/GladcnLogo.d.ts +10 -0
  164. package/dist/dev/components/GladcnLogo.d.ts.map +1 -0
  165. package/dist/dev/components/code-highlighter.d.ts +5 -0
  166. package/dist/dev/components/code-highlighter.d.ts.map +1 -0
  167. package/dist/dev/components/dev-context.d.ts +12 -0
  168. package/dist/dev/components/dev-context.d.ts.map +1 -0
  169. package/dist/dev/components/showcase.d.ts +72 -0
  170. package/dist/dev/components/showcase.d.ts.map +1 -0
  171. package/dist/dev/data.d.ts +68 -0
  172. package/dist/dev/data.d.ts.map +1 -0
  173. package/dist/dev/main.d.ts +1 -0
  174. package/dist/dev/main.d.ts.map +1 -0
  175. package/dist/dev/sections/buttons.d.ts +2 -0
  176. package/dist/dev/sections/buttons.d.ts.map +1 -0
  177. package/dist/dev/sections/display.d.ts +2 -0
  178. package/dist/dev/sections/display.d.ts.map +1 -0
  179. package/dist/dev/sections/feedback.d.ts +2 -0
  180. package/dist/dev/sections/feedback.d.ts.map +1 -0
  181. package/dist/dev/sections/forms.d.ts +2 -0
  182. package/dist/dev/sections/forms.d.ts.map +1 -0
  183. package/dist/dev/sections/interactive.d.ts +2 -0
  184. package/dist/dev/sections/interactive.d.ts.map +1 -0
  185. package/dist/dev/sections/overview.d.ts +2 -0
  186. package/dist/dev/sections/overview.d.ts.map +1 -0
  187. package/dist/dev/showcase/accordion.d.ts +2 -0
  188. package/dist/dev/showcase/accordion.d.ts.map +1 -0
  189. package/dist/dev/showcase/alert-dialog.d.ts +2 -0
  190. package/dist/dev/showcase/alert-dialog.d.ts.map +1 -0
  191. package/dist/dev/showcase/alert.d.ts +2 -0
  192. package/dist/dev/showcase/alert.d.ts.map +1 -0
  193. package/dist/dev/showcase/aspect-ratio.d.ts +2 -0
  194. package/dist/dev/showcase/aspect-ratio.d.ts.map +1 -0
  195. package/dist/dev/showcase/avatar.d.ts +2 -0
  196. package/dist/dev/showcase/avatar.d.ts.map +1 -0
  197. package/dist/dev/showcase/badge.d.ts +2 -0
  198. package/dist/dev/showcase/badge.d.ts.map +1 -0
  199. package/dist/dev/showcase/breadcrumb.d.ts +2 -0
  200. package/dist/dev/showcase/breadcrumb.d.ts.map +1 -0
  201. package/dist/dev/showcase/button.d.ts +2 -0
  202. package/dist/dev/showcase/button.d.ts.map +1 -0
  203. package/dist/dev/showcase/calendar.d.ts +2 -0
  204. package/dist/dev/showcase/calendar.d.ts.map +1 -0
  205. package/dist/dev/showcase/card.d.ts +2 -0
  206. package/dist/dev/showcase/card.d.ts.map +1 -0
  207. package/dist/dev/showcase/carousel.d.ts +2 -0
  208. package/dist/dev/showcase/carousel.d.ts.map +1 -0
  209. package/dist/dev/showcase/chart.d.ts +2 -0
  210. package/dist/dev/showcase/chart.d.ts.map +1 -0
  211. package/dist/dev/showcase/checkbox.d.ts +2 -0
  212. package/dist/dev/showcase/checkbox.d.ts.map +1 -0
  213. package/dist/dev/showcase/collapsible.d.ts +3 -0
  214. package/dist/dev/showcase/collapsible.d.ts.map +1 -0
  215. package/dist/dev/showcase/combobox.d.ts +2 -0
  216. package/dist/dev/showcase/combobox.d.ts.map +1 -0
  217. package/dist/dev/showcase/command.d.ts +2 -0
  218. package/dist/dev/showcase/command.d.ts.map +1 -0
  219. package/dist/dev/showcase/context-menu.d.ts +2 -0
  220. package/dist/dev/showcase/context-menu.d.ts.map +1 -0
  221. package/dist/dev/showcase/dialog.d.ts +2 -0
  222. package/dist/dev/showcase/dialog.d.ts.map +1 -0
  223. package/dist/dev/showcase/drawer.d.ts +2 -0
  224. package/dist/dev/showcase/drawer.d.ts.map +1 -0
  225. package/dist/dev/showcase/dropdown-menu.d.ts +2 -0
  226. package/dist/dev/showcase/dropdown-menu.d.ts.map +1 -0
  227. package/dist/dev/showcase/empty.d.ts +2 -0
  228. package/dist/dev/showcase/empty.d.ts.map +1 -0
  229. package/dist/dev/showcase/hover-card.d.ts +2 -0
  230. package/dist/dev/showcase/hover-card.d.ts.map +1 -0
  231. package/dist/dev/showcase/input-group.d.ts +2 -0
  232. package/dist/dev/showcase/input-group.d.ts.map +1 -0
  233. package/dist/dev/showcase/input-otp.d.ts +2 -0
  234. package/dist/dev/showcase/input-otp.d.ts.map +1 -0
  235. package/dist/dev/showcase/input.d.ts +2 -0
  236. package/dist/dev/showcase/input.d.ts.map +1 -0
  237. package/dist/dev/showcase/item.d.ts +2 -0
  238. package/dist/dev/showcase/item.d.ts.map +1 -0
  239. package/dist/dev/showcase/kbd.d.ts +2 -0
  240. package/dist/dev/showcase/kbd.d.ts.map +1 -0
  241. package/dist/dev/showcase/label.d.ts +2 -0
  242. package/dist/dev/showcase/label.d.ts.map +1 -0
  243. package/dist/dev/showcase/menubar.d.ts +2 -0
  244. package/dist/dev/showcase/menubar.d.ts.map +1 -0
  245. package/dist/dev/showcase/navigation-menu.d.ts +3 -0
  246. package/dist/dev/showcase/navigation-menu.d.ts.map +1 -0
  247. package/dist/dev/showcase/overview.d.ts +2 -0
  248. package/dist/dev/showcase/overview.d.ts.map +1 -0
  249. package/dist/dev/showcase/pagination.d.ts +2 -0
  250. package/dist/dev/showcase/pagination.d.ts.map +1 -0
  251. package/dist/dev/showcase/popover.d.ts +2 -0
  252. package/dist/dev/showcase/popover.d.ts.map +1 -0
  253. package/dist/dev/showcase/progress.d.ts +2 -0
  254. package/dist/dev/showcase/progress.d.ts.map +1 -0
  255. package/dist/dev/showcase/radio-group.d.ts +2 -0
  256. package/dist/dev/showcase/radio-group.d.ts.map +1 -0
  257. package/dist/dev/showcase/resizable.d.ts +2 -0
  258. package/dist/dev/showcase/resizable.d.ts.map +1 -0
  259. package/dist/dev/showcase/scroll-area.d.ts +2 -0
  260. package/dist/dev/showcase/scroll-area.d.ts.map +1 -0
  261. package/dist/dev/showcase/select.d.ts +2 -0
  262. package/dist/dev/showcase/select.d.ts.map +1 -0
  263. package/dist/dev/showcase/separator.d.ts +2 -0
  264. package/dist/dev/showcase/separator.d.ts.map +1 -0
  265. package/dist/dev/showcase/sheet.d.ts +2 -0
  266. package/dist/dev/showcase/sheet.d.ts.map +1 -0
  267. package/dist/dev/showcase/sidebar.d.ts +2 -0
  268. package/dist/dev/showcase/sidebar.d.ts.map +1 -0
  269. package/dist/dev/showcase/skeleton.d.ts +2 -0
  270. package/dist/dev/showcase/skeleton.d.ts.map +1 -0
  271. package/dist/dev/showcase/slider.d.ts +2 -0
  272. package/dist/dev/showcase/slider.d.ts.map +1 -0
  273. package/dist/dev/showcase/sonner.d.ts +2 -0
  274. package/dist/dev/showcase/sonner.d.ts.map +1 -0
  275. package/dist/dev/showcase/spinner.d.ts +2 -0
  276. package/dist/dev/showcase/spinner.d.ts.map +1 -0
  277. package/dist/dev/showcase/switch.d.ts +2 -0
  278. package/dist/dev/showcase/switch.d.ts.map +1 -0
  279. package/dist/dev/showcase/table.d.ts +2 -0
  280. package/dist/dev/showcase/table.d.ts.map +1 -0
  281. package/dist/dev/showcase/tabs.d.ts +2 -0
  282. package/dist/dev/showcase/tabs.d.ts.map +1 -0
  283. package/dist/dev/showcase/textarea.d.ts +2 -0
  284. package/dist/dev/showcase/textarea.d.ts.map +1 -0
  285. package/dist/dev/showcase/theme-provider.d.ts +2 -0
  286. package/dist/dev/showcase/theme-provider.d.ts.map +1 -0
  287. package/dist/dev/showcase/toast.d.ts +2 -0
  288. package/dist/dev/showcase/toast.d.ts.map +1 -0
  289. package/dist/dev/showcase/toggle-group.d.ts +2 -0
  290. package/dist/dev/showcase/toggle-group.d.ts.map +1 -0
  291. package/dist/dev/showcase/toggle.d.ts +2 -0
  292. package/dist/dev/showcase/toggle.d.ts.map +1 -0
  293. package/dist/dev/showcase/tooltip.d.ts +2 -0
  294. package/dist/dev/showcase/tooltip.d.ts.map +1 -0
  295. package/dist/hooks/use-controllable-state.d.ts +14 -0
  296. package/dist/hooks/use-controllable-state.d.ts.map +1 -0
  297. package/dist/hooks/use-mobile.d.ts +2 -0
  298. package/dist/hooks/use-mobile.d.ts.map +1 -0
  299. package/dist/index.cjs +5099 -0
  300. package/dist/index.cjs.map +1 -0
  301. package/dist/index.d.ts +58 -0
  302. package/dist/index.d.ts.map +1 -0
  303. package/dist/index.js +4740 -0
  304. package/dist/index.js.map +1 -0
  305. package/dist/lib/types.d.ts +4 -0
  306. package/dist/lib/types.d.ts.map +1 -0
  307. package/dist/lib/utils.d.ts +3 -0
  308. package/dist/lib/utils.d.ts.map +1 -0
  309. package/dist/preset.d.ts +18 -0
  310. package/dist/preset.d.ts.map +1 -0
  311. package/dist/test/setup.d.ts +1 -0
  312. package/dist/test/setup.d.ts.map +1 -0
  313. package/llms.txt +74 -0
  314. package/package.json +117 -0
  315. package/scripts/add-icononly-prop.ts +84 -0
  316. package/scripts/audit-best-practices.ts +114 -0
  317. package/scripts/audit-showcase.ts +262 -0
  318. package/scripts/audit-showcases.ts +83 -0
  319. package/scripts/clean-imports.ts +21 -0
  320. package/scripts/count_missing.ts +24 -0
  321. package/scripts/find-css-vars.ts +62 -0
  322. package/scripts/fix-portals.ts +90 -0
  323. package/scripts/full-audit.ts +89 -0
  324. package/scripts/merge-components.cjs +65 -0
  325. package/scripts/merge-components.js +64 -0
  326. package/scripts/optimize-barrel.ts +116 -0
  327. package/scripts/postinstall.cjs +228 -0
  328. package/scripts/refactor_divs.ts +39 -0
  329. package/scripts/remove_div_wrappers.ts +17 -0
  330. package/scripts/update-gaps.ts +83 -0
  331. package/scripts/update_showcase_codestrings.ts +87 -0
  332. package/src/components/macro/accordion-preset.test.tsx +37 -0
  333. package/src/components/macro/accordion-preset.tsx +41 -0
  334. package/src/components/macro/alert-dialog-preset.tsx +116 -0
  335. package/src/components/macro/alert-preset.tsx +94 -0
  336. package/src/components/macro/avatar-preset.tsx +54 -0
  337. package/src/components/macro/breadcrumb-preset.tsx +50 -0
  338. package/src/components/macro/card-preset.tsx +44 -0
  339. package/src/components/macro/carousel-preset.tsx +150 -0
  340. package/src/components/macro/checkbox-preset.test.tsx +49 -0
  341. package/src/components/macro/checkbox-preset.tsx +84 -0
  342. package/src/components/macro/combobox-preset.tsx +171 -0
  343. package/src/components/macro/command-preset.tsx +74 -0
  344. package/src/components/macro/date-picker.tsx +289 -0
  345. package/src/components/macro/dialog-preset.tsx +105 -0
  346. package/src/components/macro/empty-preset.tsx +46 -0
  347. package/src/components/macro/field-preset.test.tsx +69 -0
  348. package/src/components/macro/field-preset.tsx +65 -0
  349. package/src/components/macro/index.ts +21 -0
  350. package/src/components/macro/input-otp-preset.tsx +98 -0
  351. package/src/components/macro/input-preset.test.tsx +52 -0
  352. package/src/components/macro/input-preset.tsx +139 -0
  353. package/src/components/macro/pagination-preset.tsx +153 -0
  354. package/src/components/macro/progress-preset.test.tsx +65 -0
  355. package/src/components/macro/progress-preset.tsx +45 -0
  356. package/src/components/macro/radio-group-preset.tsx +115 -0
  357. package/src/components/macro/select-preset.tsx +168 -0
  358. package/src/components/macro/slider-preset.test.tsx +43 -0
  359. package/src/components/macro/slider-preset.tsx +86 -0
  360. package/src/components/macro/switch-preset.test.tsx +53 -0
  361. package/src/components/macro/switch-preset.tsx +70 -0
  362. package/src/components/macro/tabs-preset.test.tsx +31 -0
  363. package/src/components/macro/tabs-preset.tsx +51 -0
  364. package/src/components/macro/textarea-preset.test.tsx +39 -0
  365. package/src/components/macro/textarea-preset.tsx +55 -0
  366. package/src/components/micro/accordion.tsx +76 -0
  367. package/src/components/micro/alert-dialog.tsx +213 -0
  368. package/src/components/micro/alert.tsx +146 -0
  369. package/src/components/micro/aspect-ratio.tsx +38 -0
  370. package/src/components/micro/avatar.tsx +143 -0
  371. package/src/components/micro/badge.tsx +207 -0
  372. package/src/components/micro/breadcrumb.tsx +162 -0
  373. package/src/components/micro/button.test.tsx +25 -0
  374. package/src/components/micro/button.tsx +361 -0
  375. package/src/components/micro/calendar.tsx +383 -0
  376. package/src/components/micro/card.tsx +112 -0
  377. package/src/components/micro/carousel.tsx +341 -0
  378. package/src/components/micro/chart.tsx +392 -0
  379. package/src/components/micro/checkbox.tsx +74 -0
  380. package/src/components/micro/collapsible.tsx +65 -0
  381. package/src/components/micro/combobox.tsx +349 -0
  382. package/src/components/micro/command.tsx +238 -0
  383. package/src/components/micro/context-menu.tsx +285 -0
  384. package/src/components/micro/dialog.tsx +143 -0
  385. package/src/components/micro/direction.tsx +13 -0
  386. package/src/components/micro/drawer.tsx +149 -0
  387. package/src/components/micro/dropdown-menu.tsx +305 -0
  388. package/src/components/micro/empty.tsx +144 -0
  389. package/src/components/micro/field.tsx +311 -0
  390. package/src/components/micro/hover-card.tsx +86 -0
  391. package/src/components/micro/input-group.tsx +269 -0
  392. package/src/components/micro/input-otp.tsx +130 -0
  393. package/src/components/micro/input.tsx +56 -0
  394. package/src/components/micro/item.tsx +206 -0
  395. package/src/components/micro/kbd.tsx +38 -0
  396. package/src/components/micro/label.tsx +48 -0
  397. package/src/components/micro/menubar.tsx +302 -0
  398. package/src/components/micro/navigation-menu.tsx +197 -0
  399. package/src/components/micro/pagination.tsx +162 -0
  400. package/src/components/micro/popover.tsx +131 -0
  401. package/src/components/micro/progress.tsx +144 -0
  402. package/src/components/micro/radio-group.tsx +73 -0
  403. package/src/components/micro/resizable.tsx +64 -0
  404. package/src/components/micro/scroll-area.tsx +68 -0
  405. package/src/components/micro/select.tsx +234 -0
  406. package/src/components/micro/separator.tsx +37 -0
  407. package/src/components/micro/sheet.tsx +144 -0
  408. package/src/components/micro/sidebar.tsx +238 -0
  409. package/src/components/micro/skeleton.tsx +29 -0
  410. package/src/components/micro/slider.tsx +135 -0
  411. package/src/components/micro/sonner.tsx +85 -0
  412. package/src/components/micro/spinner.tsx +44 -0
  413. package/src/components/micro/switch.tsx +70 -0
  414. package/src/components/micro/table.tsx +210 -0
  415. package/src/components/micro/tabs.tsx +100 -0
  416. package/src/components/micro/textarea.tsx +53 -0
  417. package/src/components/micro/theme-provider.tsx +163 -0
  418. package/src/components/micro/toggle-group.tsx +121 -0
  419. package/src/components/micro/toggle.tsx +55 -0
  420. package/src/components/micro/tooltip.tsx +105 -0
  421. package/src/dev/App.tsx +322 -0
  422. package/src/dev/_debug_select.html +29 -0
  423. package/src/dev/components/GladcnLogo.tsx +80 -0
  424. package/src/dev/components/code-highlighter.tsx +67 -0
  425. package/src/dev/components/dev-context.tsx +31 -0
  426. package/src/dev/components/showcase.tsx +413 -0
  427. package/src/dev/data.ts +341 -0
  428. package/src/dev/index.css +55 -0
  429. package/src/dev/main.tsx +30 -0
  430. package/src/dev/sections/buttons.tsx +303 -0
  431. package/src/dev/sections/display.tsx +270 -0
  432. package/src/dev/sections/feedback.tsx +371 -0
  433. package/src/dev/sections/forms.tsx +652 -0
  434. package/src/dev/sections/interactive.tsx +51 -0
  435. package/src/dev/sections/overview.tsx +396 -0
  436. package/src/dev/showcase/accordion.tsx +947 -0
  437. package/src/dev/showcase/alert-dialog.tsx +1056 -0
  438. package/src/dev/showcase/alert.tsx +756 -0
  439. package/src/dev/showcase/aspect-ratio.tsx +339 -0
  440. package/src/dev/showcase/avatar.tsx +470 -0
  441. package/src/dev/showcase/badge.tsx +227 -0
  442. package/src/dev/showcase/breadcrumb.tsx +269 -0
  443. package/src/dev/showcase/button.tsx +309 -0
  444. package/src/dev/showcase/calendar.tsx +380 -0
  445. package/src/dev/showcase/card.tsx +448 -0
  446. package/src/dev/showcase/carousel.tsx +562 -0
  447. package/src/dev/showcase/chart.tsx +130 -0
  448. package/src/dev/showcase/checkbox.tsx +611 -0
  449. package/src/dev/showcase/collapsible.tsx +298 -0
  450. package/src/dev/showcase/combobox.tsx +777 -0
  451. package/src/dev/showcase/command.tsx +245 -0
  452. package/src/dev/showcase/context-menu.tsx +239 -0
  453. package/src/dev/showcase/dialog.tsx +1141 -0
  454. package/src/dev/showcase/drawer.tsx +392 -0
  455. package/src/dev/showcase/dropdown-menu.tsx +420 -0
  456. package/src/dev/showcase/empty.tsx +493 -0
  457. package/src/dev/showcase/hover-card.tsx +336 -0
  458. package/src/dev/showcase/input-group.tsx +511 -0
  459. package/src/dev/showcase/input-otp.tsx +404 -0
  460. package/src/dev/showcase/input.tsx +530 -0
  461. package/src/dev/showcase/item.tsx +295 -0
  462. package/src/dev/showcase/kbd.tsx +276 -0
  463. package/src/dev/showcase/label.tsx +121 -0
  464. package/src/dev/showcase/menubar.tsx +392 -0
  465. package/src/dev/showcase/navigation-menu.tsx +304 -0
  466. package/src/dev/showcase/overview.tsx +1106 -0
  467. package/src/dev/showcase/pagination.tsx +312 -0
  468. package/src/dev/showcase/popover.tsx +374 -0
  469. package/src/dev/showcase/progress.tsx +299 -0
  470. package/src/dev/showcase/radio-group.tsx +612 -0
  471. package/src/dev/showcase/resizable.tsx +237 -0
  472. package/src/dev/showcase/scroll-area.tsx +157 -0
  473. package/src/dev/showcase/select.tsx +628 -0
  474. package/src/dev/showcase/separator.tsx +126 -0
  475. package/src/dev/showcase/sheet.tsx +566 -0
  476. package/src/dev/showcase/sidebar.tsx +120 -0
  477. package/src/dev/showcase/skeleton.tsx +213 -0
  478. package/src/dev/showcase/slider.tsx +506 -0
  479. package/src/dev/showcase/sonner.tsx +376 -0
  480. package/src/dev/showcase/spinner.tsx +124 -0
  481. package/src/dev/showcase/switch.tsx +602 -0
  482. package/src/dev/showcase/table.tsx +196 -0
  483. package/src/dev/showcase/tabs.tsx +662 -0
  484. package/src/dev/showcase/textarea.tsx +498 -0
  485. package/src/dev/showcase/theme-provider.tsx +894 -0
  486. package/src/dev/showcase/toast.tsx +119 -0
  487. package/src/dev/showcase/toggle-group.tsx +223 -0
  488. package/src/dev/showcase/toggle.tsx +171 -0
  489. package/src/dev/showcase/tooltip.tsx +372 -0
  490. package/src/hooks/use-controllable-state.ts +87 -0
  491. package/src/hooks/use-mobile.ts +21 -0
  492. package/src/index.ts +62 -0
  493. package/src/lib/types.ts +14 -0
  494. package/src/lib/utils.test.ts +14 -0
  495. package/src/lib/utils.ts +6 -0
  496. package/src/preset.ts +17 -0
  497. package/src/styles/gladcn.css +116 -0
  498. package/src/styles/tokens.css +213 -0
  499. package/src/test/setup.ts +8 -0
  500. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,777 @@
1
+ import { useDevContext } from "../../dev/components/dev-context";
2
+ import { zodResolver } from "@hookform/resolvers/zod";
3
+ import { useState } from "react";
4
+ import { Controller, useForm } from "react-hook-form";
5
+ import * as z from "zod";
6
+
7
+ import {
8
+ DocsCode,
9
+ DocsP,
10
+ ExampleGrid,
11
+ ExampleSection,
12
+ Showcase,
13
+ ShowcaseDocs,
14
+ } from "../../dev/components/showcase";
15
+ import { type Size } from "../../lib/types";
16
+
17
+ import { ComboboxPreset } from "../../components/macro/combobox-preset";
18
+ import { Button } from "../../components/micro/button";
19
+ import {
20
+ Combobox,
21
+ ComboboxAnchor,
22
+ ComboboxChip,
23
+ ComboboxChips,
24
+ ComboboxChipsInput,
25
+ ComboboxClear,
26
+ ComboboxContent,
27
+ ComboboxEmpty,
28
+ ComboboxGroup,
29
+ ComboboxInput,
30
+ ComboboxItem,
31
+ ComboboxLabel,
32
+ ComboboxList,
33
+ ComboboxPortal,
34
+ ComboboxSeparator,
35
+ ComboboxTrigger,
36
+ ComboboxValue,
37
+ } from "../../components/micro/combobox";
38
+ import {
39
+ Field,
40
+ FieldContent,
41
+ FieldDescription,
42
+ FieldError,
43
+ FieldLabel,
44
+ } from "../../components/micro/field";
45
+ import {
46
+ InputGroup,
47
+ InputGroupAddon,
48
+ InputGroupInput,
49
+ } from "../../components/micro/input-group";
50
+
51
+ const frontendFrameworks = ["react", "vue", "svelte"];
52
+ const backendFrameworks = ["express", "nest"];
53
+ const allFrameworks = [...frontendFrameworks, ...backendFrameworks];
54
+ const tagItems = ["bug", "feature", "enhancement", "docs"];
55
+ const engineItems = ["v8", "spidermonkey"];
56
+
57
+ // ──────────────────────────────────────────────────────────
58
+ // RHF Form Demo (Macro)
59
+ // ──────────────────────────────────────────────────────────
60
+ const formSchema = z.object({
61
+ framework: z.string().min(1, "Vui lòng chọn một framework."),
62
+ });
63
+ type FormValues = z.infer<typeof formSchema>;
64
+
65
+ function ComboboxForm({ size }: { size: Size }) {
66
+ const form = useForm<FormValues>({
67
+ resolver: zodResolver(formSchema),
68
+ defaultValues: { framework: "" },
69
+ });
70
+
71
+ return (
72
+ <form
73
+ onSubmit={form.handleSubmit((v) => alert(JSON.stringify(v)))}
74
+ className="w-full space-y-6"
75
+ >
76
+ <Controller
77
+ control={form.control}
78
+ name="framework"
79
+ render={({ field, fieldState }) => (
80
+ <ComboboxPreset
81
+ size={size}
82
+ label="Framework"
83
+ description="Công cụ bạn sử dụng thường xuyên nhất."
84
+ placeholder="Chọn một..."
85
+ searchPlaceholder="Tìm kiếm..."
86
+ emptyText="Không tìm thấy."
87
+ options={[
88
+ { value: "react", label: "React" },
89
+ { value: "vue", label: "Vue" },
90
+ { value: "angular", label: "Angular" },
91
+ { value: "svelte", label: "Svelte" },
92
+ ]}
93
+ value={field.value}
94
+ onValueChange={field.onChange}
95
+ errorMessage={fieldState.error?.message}
96
+ />
97
+ )}
98
+ />
99
+ <Button type="submit" size={size}>
100
+ Xác nhận
101
+ </Button>
102
+ </form>
103
+ );
104
+ }
105
+
106
+ const rhfCode = `const formSchema = z.object({ framework: z.string().min(1, "Bắt buộc chọn") });
107
+
108
+ function ComboboxForm({ size }: { size: Size }) {
109
+ const form = useForm({
110
+ resolver: zodResolver(formSchema),
111
+ defaultValues: { framework: "" },
112
+ });
113
+
114
+ return (
115
+ <form onSubmit={form.handleSubmit(console.log)} className="space-y-6">
116
+ <Controller
117
+ control={form.control}
118
+ name="framework"
119
+ render={({ field, fieldState }) => (
120
+ <ComboboxPreset
121
+ size={size}
122
+ label="Framework"
123
+ placeholder="Chọn framework..."
124
+ searchPlaceholder="Tìm kiếm..."
125
+ emptyText="Không tìm thấy."
126
+ options={[
127
+ { value: "react", label: "React" },
128
+ { value: "vue", label: "Vue" }
129
+ ]}
130
+ value={field.value}
131
+ onValueChange={field.onChange}
132
+ errorMessage={fieldState.error?.message}
133
+ />
134
+ )}
135
+ />
136
+ <Button type="submit" size={size}>Gửi</Button>
137
+ </form>
138
+ );
139
+ }`;
140
+
141
+ // ──────────────────────────────────────────────────────────
142
+ // SECTION 1: Macro Content
143
+ // ──────────────────────────────────────────────────────────
144
+ function ComboboxMacroShowcase({ globalSize }: { globalSize: Size }) {
145
+ return (
146
+ <div className="space-y-10 mt-6">
147
+ <ExampleGrid>
148
+ <ExampleSection
149
+ label="Tiêu chuẩn"
150
+ description="Tương tự Select nhưng có thể gõ để tìm kiếm."
151
+ codeString={`<ComboboxPreset className="w-full"
152
+ label="Framework"
153
+ description="Hỗ trợ hàng ngàn bản ghi mà không lag."
154
+ placeholder="Chọn framework..."
155
+ searchPlaceholder="Tìm kiếm framework..."
156
+ emptyText="Không tìm thấy framework nào."
157
+ options={[
158
+ { value: "react", label: "React" },
159
+ { value: "vue", label: "Vue" },
160
+ { value: "angular", label: "Angular" },
161
+ { value: "svelte", label: "Svelte" },
162
+ ]}
163
+ />
164
+ `}
165
+ >
166
+ <ComboboxPreset
167
+ className="w-full"
168
+ size={globalSize}
169
+ label="Framework"
170
+ description="Hỗ trợ hàng ngàn bản ghi mà không lag."
171
+ placeholder="Chọn framework..."
172
+ searchPlaceholder="Tìm kiếm framework..."
173
+ emptyText="Không tìm thấy framework nào."
174
+ options={[
175
+ { value: "react", label: "React" },
176
+ { value: "vue", label: "Vue" },
177
+ { value: "angular", label: "Angular" },
178
+ { value: "svelte", label: "Svelte" },
179
+ ]}
180
+ />
181
+ </ExampleSection>
182
+
183
+ <ExampleSection
184
+ label="Trạng thái Lỗi (Error)"
185
+ description="Báo lỗi khi bỏ trống form."
186
+ codeString={`<div className="w-full flex flex-col gap-6">
187
+ <ComboboxPreset
188
+ label="Khu vực (Lỗi)"
189
+ placeholder="Chọn khu vực..."
190
+ options={[{ value: "ap", label: "Châu Á Thái Bình Dương" }]}
191
+ errorMessage="Khu vực là bắt buộc."
192
+ />
193
+ </div>
194
+ `}
195
+ >
196
+ <div className="w-full flex flex-col gap-6">
197
+ <ComboboxPreset
198
+ size={globalSize}
199
+ label="Khu vực (Lỗi)"
200
+ placeholder="Chọn khu vực..."
201
+ options={[{ value: "ap", label: "Châu Á Thái Bình Dương" }]}
202
+ errorMessage="Khu vực là bắt buộc."
203
+ />
204
+ </div>
205
+ </ExampleSection>
206
+ </ExampleGrid>
207
+
208
+ <ExampleGrid>
209
+ <ExampleSection
210
+ label="Khóa / Bất hoạt (Disabled)"
211
+ description="Người dùng không thể click hay gõ vào ô."
212
+ codeString={`<ComboboxPreset className="w-full"
213
+ label="Đội nhóm (Team)"
214
+ description="Bạn không có quyền thay đổi đội trong dự án này."
215
+ placeholder="Chọn đội..."
216
+ options={[
217
+ { value: "engineering", label: "Engineering" },
218
+ { value: "design", label: "Design" },
219
+ ]}
220
+ value="engineering"
221
+ disabled
222
+ />
223
+ `}
224
+ >
225
+ <ComboboxPreset
226
+ className="w-full"
227
+ size={globalSize}
228
+ label="Đội nhóm (Team)"
229
+ description="Bạn không có quyền thay đổi đội trong dự án này."
230
+ placeholder="Chọn đội..."
231
+ options={[
232
+ { value: "engineering", label: "Engineering" },
233
+ { value: "design", label: "Design" },
234
+ ]}
235
+ value="engineering"
236
+ disabled
237
+ />
238
+ </ExampleSection>
239
+
240
+ <ExampleSection
241
+ label="Cuộn danh sách dài (Long List)"
242
+ description="Trải nghiệm mượt mà với danh sách ảo hoá."
243
+ codeString={`<ComboboxPreset className="w-full"
244
+
245
+ label="Múi giờ (Timezone)"
246
+ placeholder="Chọn múi giờ..."
247
+ searchPlaceholder="Tìm kiếm múi giờ..."
248
+ emptyText="Không tìm thấy múi giờ."
249
+ options={Array.from({ length: 50 }).map((_, i) => ({
250
+ value: \`utc\${i - 12}\`,
251
+ label: \`UTC \${i - 12 > 0 ? '+' : ''}\${i - 12}:00\`,
252
+ }))}
253
+ />
254
+ `}
255
+ >
256
+ <ComboboxPreset
257
+ className="w-full"
258
+ size={globalSize}
259
+ label="Múi giờ (Timezone)"
260
+ placeholder="Chọn múi giờ..."
261
+ searchPlaceholder="Tìm kiếm múi giờ..."
262
+ emptyText="Không tìm thấy múi giờ."
263
+ options={Array.from({ length: 50 }).map((_, i) => ({
264
+ value: `utc${i - 12}`,
265
+ label: `UTC ${i - 12 > 0 ? "+" : ""}${i - 12}:00`,
266
+ }))}
267
+ />
268
+ </ExampleSection>
269
+ </ExampleGrid>
270
+
271
+ <ExampleGrid>
272
+ <ExampleSection
273
+ label="Tích hợp React Hook Form"
274
+ description="Sử dụng Controller để bắt giá trị."
275
+ codeString={rhfCode}
276
+ >
277
+ <ComboboxForm size={globalSize} />
278
+ </ExampleSection>
279
+ </ExampleGrid>
280
+ </div>
281
+ );
282
+ }
283
+
284
+ // ──────────────────────────────────────────────────────────
285
+ // SECTION 2: Micro Content
286
+ // ──────────────────────────────────────────────────────────
287
+ function ComboboxMicroShowcase({ globalSize }: { globalSize: Size }) {
288
+ return (
289
+ <div className="space-y-10 mt-6">
290
+ <ExampleGrid>
291
+ <ExampleSection
292
+ label="Cơ bản & Phân nhóm"
293
+ description="Sử dụng InputGroup, ComboboxAnchor, ComboboxGroup."
294
+ codeString={`<Field className="w-full">
295
+ <FieldLabel>Tìm kiếm Framework</FieldLabel>
296
+ <FieldContent>
297
+ <Combobox items={allFrameworks}>
298
+ <ComboboxAnchor className="w-full">
299
+ <InputGroup className="w-full">
300
+ <ComboboxInput
301
+ placeholder="Tìm framework..."
302
+ render={<InputGroupInput />}
303
+ />
304
+ <InputGroupAddon align="end">
305
+ <ComboboxTrigger className="flex h-full cursor-default items-center justify-center px-2.5 outline-none group-has-data-[slot=combobox-clear]/input-group:hidden disabled:cursor-not-allowed disabled:opacity-50" />
306
+ <ComboboxClear />
307
+ </InputGroupAddon>
308
+ </InputGroup>
309
+ </ComboboxAnchor>
310
+ <ComboboxPortal><ComboboxContent>
311
+ <ComboboxEmpty>Không tìm thấy.</ComboboxEmpty>
312
+ <ComboboxList>
313
+ <ComboboxGroup>
314
+ <ComboboxLabel>Frontend</ComboboxLabel>
315
+ <ComboboxItem value="react">React</ComboboxItem>
316
+ <ComboboxItem value="vue">Vue</ComboboxItem>
317
+ <ComboboxItem value="svelte">Svelte</ComboboxItem>
318
+ </ComboboxGroup>
319
+ <ComboboxSeparator />
320
+ <ComboboxGroup>
321
+ <ComboboxLabel>Backend</ComboboxLabel>
322
+ <ComboboxItem value="express">Express</ComboboxItem>
323
+ <ComboboxItem value="nest">NestJS</ComboboxItem>
324
+ </ComboboxGroup>
325
+ </ComboboxList>
326
+ </ComboboxContent></ComboboxPortal>
327
+ </Combobox>
328
+ </FieldContent>
329
+ </Field>
330
+ `}
331
+ >
332
+ <Field size={globalSize} className="w-full">
333
+ <FieldLabel>Tìm kiếm Framework</FieldLabel>
334
+ <FieldContent>
335
+ <Combobox items={allFrameworks}>
336
+ <ComboboxAnchor className="w-full">
337
+ <InputGroup size={globalSize} className="w-full">
338
+ <ComboboxInput
339
+ placeholder="Tìm framework..."
340
+ render={<InputGroupInput />}
341
+ />
342
+ <InputGroupAddon align="end">
343
+ <ComboboxTrigger className="flex h-full cursor-default items-center justify-center px-2.5 outline-none group-has-data-[slot=combobox-clear]/input-group:hidden disabled:cursor-not-allowed disabled:opacity-50" />
344
+ <ComboboxClear />
345
+ </InputGroupAddon>
346
+ </InputGroup>
347
+ </ComboboxAnchor>
348
+
349
+ <ComboboxPortal>
350
+ <ComboboxContent>
351
+ <ComboboxEmpty>Không tìm thấy.</ComboboxEmpty>
352
+ <ComboboxList>
353
+ <ComboboxGroup>
354
+ <ComboboxLabel>Frontend</ComboboxLabel>
355
+ <ComboboxItem value="react">React</ComboboxItem>
356
+ <ComboboxItem value="vue">Vue</ComboboxItem>
357
+ <ComboboxItem value="svelte">Svelte</ComboboxItem>
358
+ </ComboboxGroup>
359
+ <ComboboxSeparator />
360
+ <ComboboxGroup>
361
+ <ComboboxLabel>Backend</ComboboxLabel>
362
+ <ComboboxItem value="express">Express</ComboboxItem>
363
+ <ComboboxItem value="nest">NestJS</ComboboxItem>
364
+ </ComboboxGroup>
365
+ </ComboboxList>
366
+ </ComboboxContent>
367
+ </ComboboxPortal>
368
+ </Combobox>
369
+ </FieldContent>
370
+ </Field>
371
+ </ExampleSection>
372
+
373
+ <ExampleSection
374
+ label="Chọn nhiều (Multi-select Chips)"
375
+ description="Sử dụng ComboboxChips và ComboboxChip thay cho Input."
376
+ codeString={`<Field className="w-full">
377
+ <FieldLabel>Gán thẻ (Tags)</FieldLabel>
378
+ <FieldContent>
379
+ <Combobox items={tagItems} multiple>
380
+ <ComboboxChips>
381
+ <ComboboxChip value="bug">Lỗi (Bug)</ComboboxChip>
382
+ <ComboboxChip value="feature">
383
+ Tính năng (Feature)
384
+ </ComboboxChip>
385
+ <ComboboxChipsInput placeholder="Thêm thẻ..." />
386
+ </ComboboxChips>
387
+ <ComboboxPortal><ComboboxContent>
388
+ <ComboboxEmpty>Không tìm thấy thẻ.</ComboboxEmpty>
389
+ <ComboboxList>
390
+ <ComboboxItem value="bug">Lỗi (Bug)</ComboboxItem>
391
+ <ComboboxItem value="feature">
392
+ Tính năng (Feature)
393
+ </ComboboxItem>
394
+ <ComboboxItem value="enhancement">Cải thiện</ComboboxItem>
395
+ <ComboboxItem value="docs">Tài liệu</ComboboxItem>
396
+ </ComboboxList>
397
+ </ComboboxContent></ComboboxPortal>
398
+ </Combobox>
399
+ </FieldContent>
400
+ <FieldDescription>
401
+ Bạn có thể chọn nhiều thẻ cùng lúc.
402
+ </FieldDescription>
403
+ </Field>
404
+ `}
405
+ >
406
+ <Field size={globalSize} className="w-full">
407
+ <FieldLabel>Gán thẻ (Tags)</FieldLabel>
408
+ <FieldContent>
409
+ <Combobox items={tagItems} multiple>
410
+ <ComboboxChips size={globalSize}>
411
+ <ComboboxChip value="bug">Lỗi (Bug)</ComboboxChip>
412
+ <ComboboxChip value="feature">
413
+ Tính năng (Feature)
414
+ </ComboboxChip>
415
+ <ComboboxChipsInput placeholder="Thêm thẻ..." />
416
+ </ComboboxChips>
417
+
418
+ <ComboboxPortal>
419
+ <ComboboxContent>
420
+ <ComboboxEmpty>Không tìm thấy thẻ.</ComboboxEmpty>
421
+ <ComboboxList>
422
+ <ComboboxItem value="bug">Lỗi (Bug)</ComboboxItem>
423
+ <ComboboxItem value="feature">
424
+ Tính năng (Feature)
425
+ </ComboboxItem>
426
+ <ComboboxItem value="enhancement">Cải thiện</ComboboxItem>
427
+ <ComboboxItem value="docs">Tài liệu</ComboboxItem>
428
+ </ComboboxList>
429
+ </ComboboxContent>
430
+ </ComboboxPortal>
431
+ </Combobox>
432
+ </FieldContent>
433
+ <FieldDescription>
434
+ Bạn có thể chọn nhiều thẻ cùng lúc.
435
+ </FieldDescription>
436
+ </Field>
437
+ </ExampleSection>
438
+ </ExampleGrid>
439
+
440
+ <ExampleGrid>
441
+ <ExampleSection
442
+ label="Disabled thủ công"
443
+ description="Truyền disabled vào InputGroupInput và ComboboxTrigger."
444
+ codeString={`<Field className="w-full">
445
+ <FieldLabel>Tìm kiếm (Disabled)</FieldLabel>
446
+ <FieldContent>
447
+ <Combobox items={["react"]}>
448
+ <ComboboxAnchor className="w-full">
449
+ <InputGroup className="w-full">
450
+ <ComboboxInput
451
+ placeholder="Tìm kiếm..."
452
+ disabled
453
+ render={<InputGroupInput disabled />}
454
+ />
455
+ <InputGroupAddon align="end">
456
+ <ComboboxTrigger className="flex h-full cursor-default items-center justify-center px-2.5 outline-none group-has-data-[slot=combobox-clear]/input-group:hidden disabled:cursor-not-allowed disabled:opacity-50" disabled />
457
+ </InputGroupAddon>
458
+ </InputGroup>
459
+ </ComboboxAnchor>
460
+ <ComboboxPortal><ComboboxContent>
461
+ <ComboboxList>
462
+ <ComboboxItem value="react">React</ComboboxItem>
463
+ </ComboboxList>
464
+ </ComboboxContent></ComboboxPortal>
465
+ </Combobox>
466
+ </FieldContent>
467
+ </Field>
468
+ `}
469
+ >
470
+ <Field size={globalSize} className="w-full">
471
+ <FieldLabel>Tìm kiếm (Disabled)</FieldLabel>
472
+ <FieldContent>
473
+ <Combobox items={["react"]}>
474
+ <ComboboxAnchor className="w-full">
475
+ <InputGroup size={globalSize} className="w-full">
476
+ <ComboboxInput
477
+ placeholder="Tìm kiếm..."
478
+ disabled
479
+ render={<InputGroupInput disabled />}
480
+ />
481
+ <InputGroupAddon align="end">
482
+ <ComboboxTrigger
483
+ className="flex h-full cursor-default items-center justify-center px-2.5 outline-none group-has-data-[slot=combobox-clear]/input-group:hidden disabled:cursor-not-allowed disabled:opacity-50"
484
+ disabled
485
+ />
486
+ </InputGroupAddon>
487
+ </InputGroup>
488
+ </ComboboxAnchor>
489
+
490
+ <ComboboxPortal>
491
+ <ComboboxContent>
492
+ <ComboboxList>
493
+ <ComboboxItem value="react">React</ComboboxItem>
494
+ </ComboboxList>
495
+ </ComboboxContent>
496
+ </ComboboxPortal>
497
+ </Combobox>
498
+ </FieldContent>
499
+ </Field>
500
+ </ExampleSection>
501
+
502
+ <ExampleSection
503
+ label="Trạng thái Lỗi (Invalid)"
504
+ description="Gắn aria-invalid vào ô nhập liệu."
505
+ codeString={`<Field data-invalid={true} className="w-full">
506
+ <FieldLabel>Mã giảm giá</FieldLabel>
507
+ <FieldContent>
508
+ <Combobox items={["sale20", "sale50"]}>
509
+ <ComboboxAnchor className="w-full">
510
+ <InputGroup className="w-full">
511
+ <ComboboxInput
512
+ placeholder="Nhập mã..."
513
+ aria-invalid={true}
514
+ render={<InputGroupInput />}
515
+ />
516
+ <InputGroupAddon align="end">
517
+ <ComboboxTrigger className="flex h-full cursor-default items-center justify-center px-2.5 outline-none group-has-data-[slot=combobox-clear]/input-group:hidden disabled:cursor-not-allowed disabled:opacity-50" />
518
+ <ComboboxClear />
519
+ </InputGroupAddon>
520
+ </InputGroup>
521
+ </ComboboxAnchor>
522
+ <ComboboxPortal><ComboboxContent>
523
+ <ComboboxEmpty>Không tìm thấy mã.</ComboboxEmpty>
524
+ <ComboboxList>
525
+ <ComboboxItem value="sale20">Giảm 20%</ComboboxItem>
526
+ <ComboboxItem value="sale50">Giảm 50%</ComboboxItem>
527
+ </ComboboxList>
528
+ </ComboboxContent></ComboboxPortal>
529
+ </Combobox>
530
+ </FieldContent>
531
+ <FieldError>Mã này đã hết hạn.</FieldError>
532
+ </Field>
533
+ `}
534
+ >
535
+ <Field size={globalSize} data-invalid={true} className="w-full">
536
+ <FieldLabel>Mã giảm giá</FieldLabel>
537
+ <FieldContent>
538
+ <Combobox items={["sale20", "sale50"]}>
539
+ <ComboboxAnchor className="w-full">
540
+ <InputGroup size={globalSize} className="w-full">
541
+ <ComboboxInput
542
+ placeholder="Nhập mã..."
543
+ aria-invalid={true}
544
+ render={<InputGroupInput />}
545
+ />
546
+ <InputGroupAddon align="end">
547
+ <ComboboxTrigger className="flex h-full cursor-default items-center justify-center px-2.5 outline-none group-has-data-[slot=combobox-clear]/input-group:hidden disabled:cursor-not-allowed disabled:opacity-50" />
548
+ <ComboboxClear />
549
+ </InputGroupAddon>
550
+ </InputGroup>
551
+ </ComboboxAnchor>
552
+
553
+ <ComboboxPortal>
554
+ <ComboboxContent>
555
+ <ComboboxEmpty>Không tìm thấy mã.</ComboboxEmpty>
556
+ <ComboboxList>
557
+ <ComboboxItem value="sale20">Giảm 20%</ComboboxItem>
558
+ <ComboboxItem value="sale50">Giảm 50%</ComboboxItem>
559
+ </ComboboxList>
560
+ </ComboboxContent>
561
+ </ComboboxPortal>
562
+ </Combobox>
563
+ </FieldContent>
564
+ <FieldError>Mã này đã hết hạn.</FieldError>
565
+ </Field>
566
+ </ExampleSection>
567
+ </ExampleGrid>
568
+
569
+ <ExampleGrid>
570
+ <ExampleSection
571
+ label="Giao diện Nút (With Trigger)"
572
+ description="Combobox dùng nút bấm (giống Select) thay vì ô nhập chữ (Input)."
573
+ codeString={`<Field className="w-full">
574
+ <FieldLabel>Chọn Engine</FieldLabel>
575
+ <FieldContent>
576
+ <Combobox items={engineItems}>
577
+ <ComboboxTrigger className="w-full justify-between flex items-center border border-border rounded-md p-2 hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring">
578
+ <ComboboxValue placeholder="Chọn một engine" />
579
+ </ComboboxTrigger>
580
+ <ComboboxPortal><ComboboxContent>
581
+ <div className="p-1">
582
+ <InputGroup className="w-full">
583
+ <ComboboxInput
584
+ placeholder="Tìm engine..."
585
+ render={<InputGroupInput />}
586
+ />
587
+ </InputGroup>
588
+ </div>
589
+ <ComboboxEmpty>Không tìm thấy.</ComboboxEmpty>
590
+ <ComboboxList>
591
+ <ComboboxItem value="v8">V8 (Chrome)</ComboboxItem>
592
+ <ComboboxItem value="spidermonkey">SpiderMonkey (Firefox)</ComboboxItem>
593
+ </ComboboxList>
594
+ </ComboboxContent></ComboboxPortal>
595
+ </Combobox>
596
+ </FieldContent>
597
+ </Field>
598
+ `}
599
+ >
600
+ <Field size={globalSize} className="w-full">
601
+ <FieldLabel>Chọn Engine</FieldLabel>
602
+ <FieldContent>
603
+ <Combobox items={engineItems}>
604
+ <ComboboxTrigger className="w-full justify-between flex items-center border border-border rounded-md p-2 hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring">
605
+ <ComboboxValue placeholder="Chọn một engine" />
606
+ </ComboboxTrigger>
607
+
608
+ <ComboboxPortal>
609
+ <ComboboxContent>
610
+ <div className="p-1">
611
+ <InputGroup size={globalSize} className="w-full">
612
+ <ComboboxInput
613
+ placeholder="Tìm engine..."
614
+ render={<InputGroupInput />}
615
+ />
616
+ </InputGroup>
617
+ </div>
618
+ <ComboboxEmpty>Không tìm thấy.</ComboboxEmpty>
619
+ <ComboboxList>
620
+ <ComboboxItem value="v8">V8 (Chrome)</ComboboxItem>
621
+ <ComboboxItem value="spidermonkey">
622
+ SpiderMonkey (Firefox)
623
+ </ComboboxItem>
624
+ </ComboboxList>
625
+ </ComboboxContent>
626
+ </ComboboxPortal>
627
+ </Combobox>
628
+ </FieldContent>
629
+ </Field>
630
+ </ExampleSection>
631
+ </ExampleGrid>
632
+
633
+ <ExampleSection
634
+ label="🧭 Use Case Comparison"
635
+ description="So sánh nhanh khi nào dùng Micro và Macro."
636
+ fullWidth
637
+ codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
638
+ {/* Story 1: Macro wins */}
639
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
640
+ <div className="flex items-start gap-3">
641
+ <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
642
+ <svg xmlns="http://www.w3.org/2000/svg" className="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
643
+ </span>
644
+ <div>
645
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Story 1 · Dùng Macro</p>
646
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">Single Select tự động hoàn thành</h3>
647
+ </div>
648
+ </div>
649
+ <p className="text-xs text-muted-foreground leading-relaxed">
650
+ Bạn cần một form chọn Thành phố. Số lượng thành phố quá lớn nên không dùng Select được, phải dùng Combobox để gõ tìm. <DocsCode>ComboboxPreset</DocsCode> sinh ra để giải quyết đúng bài toán chọn 1 giá trị từ tập lớn này.
651
+ </p>
652
+ </div>
653
+
654
+ {/* Story 2: Micro wins */}
655
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
656
+ <div className="flex items-start gap-3">
657
+ <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
658
+ <svg xmlns="http://www.w3.org/2000/svg" className="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>
659
+ </span>
660
+ <div>
661
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Story 2 · Dùng Micro</p>
662
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">Gán thẻ (Multi-select)</h3>
663
+ </div>
664
+ </div>
665
+ <p className="text-xs text-muted-foreground leading-relaxed">
666
+ Bạn làm form tạo bài viết mới và cần gán nhiều Thẻ (Tags) cho bài viết. Macro không hỗ trợ Multi-select. Bạn buộc phải dùng Micro kết hợp với cụm <DocsCode>{\`<ComboboxChips />\`}</DocsCode>.
667
+ </p>
668
+ </div>
669
+ </div>
670
+ `}
671
+ >
672
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
673
+ {/* Story 1: Macro wins */}
674
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
675
+ <div className="flex items-start gap-3">
676
+ <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
677
+ <svg
678
+ xmlns="http://www.w3.org/2000/svg"
679
+ className="size-4"
680
+ viewBox="0 0 24 24"
681
+ fill="none"
682
+ stroke="currentColor"
683
+ strokeWidth="2"
684
+ strokeLinecap="round"
685
+ strokeLinejoin="round"
686
+ aria-hidden="true"
687
+ >
688
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
689
+ </svg>
690
+ </span>
691
+ <div>
692
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
693
+ Story 1 · Dùng Macro
694
+ </p>
695
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
696
+ Single Select tự động hoàn thành
697
+ </h3>
698
+ </div>
699
+ </div>
700
+ <p className="text-xs text-muted-foreground leading-relaxed">
701
+ Bạn cần một form chọn Thành phố. Số lượng thành phố quá lớn nên
702
+ không dùng Select được, phải dùng Combobox để gõ tìm.{" "}
703
+ <DocsCode>ComboboxPreset</DocsCode> sinh ra để giải quyết đúng bài
704
+ toán chọn 1 giá trị từ tập lớn này.
705
+ </p>
706
+ </div>
707
+
708
+ {/* Story 2: Micro wins */}
709
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
710
+ <div className="flex items-start gap-3">
711
+ <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
712
+ <svg
713
+ xmlns="http://www.w3.org/2000/svg"
714
+ className="size-4"
715
+ viewBox="0 0 24 24"
716
+ fill="none"
717
+ stroke="currentColor"
718
+ strokeWidth="2"
719
+ strokeLinecap="round"
720
+ strokeLinejoin="round"
721
+ aria-hidden="true"
722
+ >
723
+ <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" />
724
+ </svg>
725
+ </span>
726
+ <div>
727
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
728
+ Story 2 · Dùng Micro
729
+ </p>
730
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
731
+ Gán thẻ (Multi-select)
732
+ </h3>
733
+ </div>
734
+ </div>
735
+ <p className="text-xs text-muted-foreground leading-relaxed">
736
+ Bạn làm form tạo bài viết mới và cần gán nhiều Thẻ (Tags) cho bài
737
+ viết. Macro không hỗ trợ Multi-select. Bạn buộc phải dùng Micro
738
+ kết hợp với cụm <DocsCode>{`<ComboboxChips />`}</DocsCode>.
739
+ </p>
740
+ </div>
741
+ </div>
742
+ </ExampleSection>
743
+ </div>
744
+ );
745
+ }
746
+
747
+ // ──────────────────────────────────────────────────────────
748
+ // SECTION 3: Entry point
749
+ // ──────────────────────────────────────────────────────────
750
+ export default function ComboboxShowcase() {
751
+ const { size: globalSize } = useDevContext();
752
+ return (
753
+ <Showcase
754
+ title="Combobox"
755
+ description="Thành phần mở rộng của Select, cho phép người dùng gõ phím để tìm kiếm và lọc qua các tập dữ liệu lớn."
756
+ generalConcept={
757
+ <ShowcaseDocs>
758
+ <DocsP>
759
+ Dùng để chọn một hoặc nhiều giá trị từ một danh sách lớn. Khác với
760
+ Select, Combobox có ô nhập liệu để người dùng có thể gõ từ khóa tìm
761
+ kiếm và lọc các tùy chọn một cách nhanh chóng.
762
+ </DocsP>
763
+ </ShowcaseDocs>
764
+ }
765
+ tabs={[
766
+ {
767
+ label: "Micro (Primitive)",
768
+ content: <ComboboxMicroShowcase globalSize={globalSize} />,
769
+ },
770
+ {
771
+ label: "Macro (Preset)",
772
+ content: <ComboboxMacroShowcase globalSize={globalSize} />,
773
+ },
774
+ ]}
775
+ />
776
+ );
777
+ }