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,628 @@
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
+ DocsH3,
10
+ DocsP,
11
+ ExampleGrid,
12
+ ExampleSection,
13
+ Showcase,
14
+ ShowcaseDocs,
15
+ } from "../../dev/components/showcase";
16
+ import { type Size } from "../../lib/types";
17
+
18
+ import { SelectPreset } from "../../components/macro/select-preset";
19
+ import { Button } from "../../components/micro/button";
20
+ import {
21
+ Field,
22
+ FieldContent,
23
+ FieldDescription,
24
+ FieldError,
25
+ FieldLabel,
26
+ } from "../../components/micro/field";
27
+ import {
28
+ Select,
29
+ SelectContent,
30
+ SelectGroup,
31
+ SelectItem,
32
+ SelectLabel,
33
+ SelectScrollDownButton,
34
+ SelectScrollUpButton,
35
+ SelectSeparator,
36
+ SelectTrigger,
37
+ SelectValue,
38
+ SelectPortal,
39
+ } from "../../components/micro/select";
40
+
41
+ // ──────────────────────────────────────────────────────────
42
+ // RHF Form Demo (Macro)
43
+ // ──────────────────────────────────────────────────────────
44
+ const formSchema = z.object({
45
+ language: z.string().min(1, "Vui lòng chọn một ngôn ngữ."),
46
+ });
47
+ type FormValues = z.infer<typeof formSchema>;
48
+
49
+ function SelectForm({ size }: { size: Size }) {
50
+ const form = useForm<FormValues>({
51
+ resolver: zodResolver(formSchema),
52
+ defaultValues: { language: "" },
53
+ });
54
+
55
+ return (
56
+ <form
57
+ onSubmit={form.handleSubmit((v) => alert(JSON.stringify(v)))}
58
+ className="w-full space-y-6"
59
+ >
60
+ <Controller
61
+ control={form.control}
62
+ name="language"
63
+ render={({ field, fieldState }) => (
64
+ <SelectPreset
65
+ size={size}
66
+ label="Ngôn ngữ"
67
+ description="Ngôn ngữ giao diện bạn muốn sử dụng."
68
+ placeholder="Chọn một ngôn ngữ..."
69
+ options={[
70
+ { value: "en", label: "Tiếng Anh (English)" },
71
+ { value: "vi", label: "Tiếng Việt (Vietnamese)" },
72
+ { value: "fr", label: "Tiếng Pháp (French)" },
73
+ ]}
74
+ value={field.value}
75
+ onValueChange={field.onChange}
76
+ errorMessage={fieldState.error?.message}
77
+ />
78
+ )}
79
+ />
80
+ <Button type="submit" size={size}>
81
+ Xác nhận
82
+ </Button>
83
+ </form>
84
+ );
85
+ }
86
+
87
+ const rhfCode = `const formSchema = z.object({ language: z.string().min(1, "Bắt buộc chọn") });
88
+
89
+ function SelectForm({ size }: { size: Size }) {
90
+ const form = useForm({
91
+ resolver: zodResolver(formSchema),
92
+ defaultValues: { language: "" },
93
+ });
94
+
95
+ return (
96
+ <form onSubmit={form.handleSubmit(console.log)} className="space-y-6">
97
+ <Controller
98
+ control={form.control}
99
+ name="language"
100
+ render={({ field, fieldState }) => (
101
+ <SelectPreset
102
+ size={size}
103
+ label="Ngôn ngữ"
104
+ placeholder="Chọn ngôn ngữ..."
105
+ options={[
106
+ { value: "en", label: "English" },
107
+ { value: "vi", label: "Tiếng Việt" }
108
+ ]}
109
+ value={field.value}
110
+ onValueChange={field.onChange}
111
+ errorMessage={fieldState.error?.message}
112
+ />
113
+ )}
114
+ />
115
+ <Button type="submit" size={size}>Gửi</Button>
116
+ </form>
117
+ );
118
+ }`;
119
+
120
+ // ──────────────────────────────────────────────────────────
121
+ // SECTION 1: Macro Content
122
+ // ──────────────────────────────────────────────────────────
123
+ function SelectMacroShowcase({ globalSize }: { globalSize: Size }) {
124
+ return (
125
+ <div className="space-y-10 mt-6">
126
+ <ExampleGrid>
127
+ <ExampleSection
128
+ label="Tiêu chuẩn"
129
+ description="Trình thả xuống cơ bản với mảng options."
130
+ codeString={`<SelectPreset className="w-full"
131
+ label="Trái cây yêu thích"
132
+ description="Chọn một loại trái cây bạn thích nhất."
133
+ placeholder="Chọn trái cây..."
134
+ options={[
135
+ { value: "apple", label: "Táo (Apple)" },
136
+ { value: "banana", label: "Chuối (Banana)" },
137
+ { value: "cherry", label: "Anh đào (Cherry)" },
138
+ ]}
139
+ />
140
+ `}
141
+ >
142
+ <SelectPreset
143
+ className="w-full"
144
+ size={globalSize}
145
+ label="Trái cây yêu thích"
146
+ description="Chọn một loại trái cây bạn thích nhất."
147
+ placeholder="Chọn trái cây..."
148
+ options={[
149
+ { value: "apple", label: "Táo (Apple)" },
150
+ { value: "banana", label: "Chuối (Banana)" },
151
+ { value: "cherry", label: "Anh đào (Cherry)" },
152
+ ]}
153
+ />
154
+ </ExampleSection>
155
+
156
+ <ExampleSection
157
+ label="Trạng thái Lỗi (Error)"
158
+ description="Báo lỗi khi form submit mà user chưa chọn."
159
+ codeString={`<div className="w-full flex flex-col gap-6">
160
+ <SelectPreset
161
+ label="Framework (Lỗi)"
162
+ placeholder="Chọn một framework..."
163
+ options={[{ value: "react", label: "React" }, { value: "vue", label: "Vue" }]}
164
+ errorMessage="Vui lòng chọn một framework để tiếp tục."
165
+ />
166
+ </div>
167
+ `}
168
+ >
169
+ <div className="w-full flex flex-col gap-6">
170
+ <SelectPreset
171
+ size={globalSize}
172
+ label="Framework (Lỗi)"
173
+ placeholder="Chọn một framework..."
174
+ options={[
175
+ { value: "react", label: "React" },
176
+ { value: "vue", label: "Vue" },
177
+ ]}
178
+ errorMessage="Vui lòng chọn một framework để tiếp tục."
179
+ />
180
+ </div>
181
+ </ExampleSection>
182
+ </ExampleGrid>
183
+
184
+ <ExampleGrid>
185
+ <ExampleSection
186
+ label="Khóa / Bất hoạt (Disabled)"
187
+ description="Người dùng không thể mở danh sách."
188
+ codeString={`<SelectPreset className="w-full"
189
+ label="Gói tài khoản"
190
+ description="Bạn không thể thay đổi gói cước khi chưa thanh toán nợ."
191
+ placeholder="Chọn gói..."
192
+ value="pro"
193
+ options={[
194
+ { value: "basic", label: "Cơ bản (Free)" },
195
+ { value: "pro", label: "Chuyên nghiệp (Pro)" },
196
+ ]}
197
+ disabled
198
+ />
199
+ `}
200
+ >
201
+ <SelectPreset
202
+ className="w-full"
203
+ size={globalSize}
204
+ label="Gói tài khoản"
205
+ description="Bạn không thể thay đổi gói cước khi chưa thanh toán nợ."
206
+ placeholder="Chọn gói..."
207
+ value="pro"
208
+ options={[
209
+ { value: "basic", label: "Cơ bản (Free)" },
210
+ { value: "pro", label: "Chuyên nghiệp (Pro)" },
211
+ ]}
212
+ disabled
213
+ />
214
+ </ExampleSection>
215
+
216
+ <ExampleSection
217
+ label="Nhãn phức tạp (Custom Content)"
218
+ description="Truyền React Node vào Label để tạo giao diện phong phú."
219
+ codeString={`<SelectPreset
220
+ label={
221
+ <span className="flex items-center gap-2">
222
+ Quốc gia cư trú
223
+ <span className="text-destructive">*</span>
224
+ </span>
225
+ }
226
+ description="Thông tin này được sử dụng cho mục đích tính thuế, phải khớp với địa chỉ thanh toán."
227
+ placeholder="Chọn quốc gia..."
228
+ options={[
229
+ { value: "us", label: "United States" },
230
+ { value: "vn", label: "Việt Nam" },
231
+ ]}
232
+ />
233
+ `}
234
+ >
235
+ <SelectPreset
236
+ size={globalSize}
237
+ label={
238
+ <span className="flex items-center gap-2">
239
+ Quốc gia cư trú
240
+ <span className="text-destructive">*</span>
241
+ </span>
242
+ }
243
+ description="Thông tin này được sử dụng cho mục đích tính thuế, phải khớp với địa chỉ thanh toán."
244
+ placeholder="Chọn quốc gia..."
245
+ options={[
246
+ { value: "us", label: "United States" },
247
+ { value: "vn", label: "Việt Nam" },
248
+ ]}
249
+ />
250
+ </ExampleSection>
251
+ </ExampleGrid>
252
+
253
+ <ExampleGrid>
254
+ <ExampleSection
255
+ label="Tích hợp React Hook Form"
256
+ description="Sử dụng Controller để bắt giá trị."
257
+ codeString={rhfCode}
258
+ >
259
+ <SelectForm size={globalSize} />
260
+ </ExampleSection>
261
+ </ExampleGrid>
262
+ </div>
263
+ );
264
+ }
265
+
266
+ // ──────────────────────────────────────────────────────────
267
+ // SECTION 2: Micro Content
268
+ // ──────────────────────────────────────────────────────────
269
+ function SelectMicroShowcase({ globalSize }: { globalSize: Size }) {
270
+ return (
271
+ <div className="space-y-10 mt-6">
272
+ <ExampleGrid>
273
+ <ExampleSection
274
+ label="Cơ bản (Primitive)"
275
+ description="Ghép nối thủ công bằng cách bọc Field."
276
+ codeString={`<Field className="w-full">
277
+ <FieldLabel>Framework</FieldLabel>
278
+ <FieldContent>
279
+ <Select items={{ next: "Next.js", vite: "Vite", remix: "Remix" }}>
280
+ <SelectTrigger>
281
+ <SelectValue placeholder="Chọn framework..." />
282
+ </SelectTrigger>
283
+ <SelectPortal><SelectContent>
284
+ <SelectScrollUpButton />
285
+ <SelectItem value="next">Next.js</SelectItem>
286
+ <SelectItem value="vite">Vite</SelectItem>
287
+ <SelectItem value="remix">Remix</SelectItem>
288
+ <SelectScrollDownButton />
289
+ </SelectContent></SelectPortal>
290
+ </Select>
291
+ </FieldContent>
292
+ <FieldDescription>
293
+ Chọn công nghệ bạn muốn sử dụng.
294
+ </FieldDescription>
295
+ </Field>
296
+ `}
297
+ >
298
+ <Field size={globalSize} className="w-full">
299
+ <FieldLabel>Framework</FieldLabel>
300
+ <FieldContent>
301
+ <Select items={{ next: "Next.js", vite: "Vite", remix: "Remix" }}>
302
+ <SelectTrigger size={globalSize}>
303
+ <SelectValue placeholder="Chọn framework..." />
304
+ </SelectTrigger>
305
+
306
+ <SelectPortal>
307
+ <SelectContent>
308
+ <SelectScrollUpButton />
309
+ <SelectItem value="next">Next.js</SelectItem>
310
+ <SelectItem value="vite">Vite</SelectItem>
311
+ <SelectItem value="remix">Remix</SelectItem>
312
+ <SelectScrollDownButton />
313
+ </SelectContent>
314
+ </SelectPortal>
315
+ </Select>
316
+ </FieldContent>
317
+ <FieldDescription>
318
+ Chọn công nghệ bạn muốn sử dụng.
319
+ </FieldDescription>
320
+ </Field>
321
+ </ExampleSection>
322
+
323
+ <ExampleSection
324
+ label="Phân nhóm (Grouped)"
325
+ description="Sử dụng SelectGroup, SelectLabel và SelectSeparator."
326
+ codeString={`<Field className="w-full">
327
+ <FieldLabel>Trái cây</FieldLabel>
328
+ <FieldContent>
329
+ <Select
330
+ items={{
331
+ orange: "Orange",
332
+ lemon: "Lemon",
333
+ strawberry: "Strawberry",
334
+ blueberry: "Blueberry",
335
+ }}
336
+ >
337
+ <SelectTrigger>
338
+ <SelectValue placeholder="Chọn loại quả..." />
339
+ </SelectTrigger>
340
+ <SelectPortal><SelectContent>
341
+ <SelectGroup>
342
+ <SelectLabel>Họ cam chanh (Citrus)</SelectLabel>
343
+ <SelectItem value="orange">Orange</SelectItem>
344
+ <SelectItem value="lemon">Lemon</SelectItem>
345
+ </SelectGroup>
346
+ <SelectSeparator />
347
+ <SelectGroup>
348
+ <SelectLabel>Họ dâu (Berry)</SelectLabel>
349
+ <SelectItem value="strawberry">Strawberry</SelectItem>
350
+ <SelectItem value="blueberry">Blueberry</SelectItem>
351
+ </SelectGroup>
352
+ </SelectContent></SelectPortal>
353
+ </Select>
354
+ </FieldContent>
355
+ </Field>
356
+ `}
357
+ >
358
+ <Field size={globalSize} className="w-full">
359
+ <FieldLabel>Trái cây</FieldLabel>
360
+ <FieldContent>
361
+ <Select
362
+ items={{
363
+ orange: "Orange",
364
+ lemon: "Lemon",
365
+ strawberry: "Strawberry",
366
+ blueberry: "Blueberry",
367
+ }}
368
+ >
369
+ <SelectTrigger size={globalSize}>
370
+ <SelectValue placeholder="Chọn loại quả..." />
371
+ </SelectTrigger>
372
+ <SelectPortal>
373
+ <SelectContent>
374
+ <SelectGroup>
375
+ <SelectLabel>Họ cam chanh (Citrus)</SelectLabel>
376
+ <SelectItem value="orange">Orange</SelectItem>
377
+ <SelectItem value="lemon">Lemon</SelectItem>
378
+ </SelectGroup>
379
+ <SelectSeparator />
380
+ <SelectGroup>
381
+ <SelectLabel>Họ dâu (Berry)</SelectLabel>
382
+ <SelectItem value="strawberry">Strawberry</SelectItem>
383
+ <SelectItem value="blueberry">Blueberry</SelectItem>
384
+ </SelectGroup>
385
+ </SelectContent>
386
+ </SelectPortal>
387
+ </Select>
388
+ </FieldContent>
389
+ </Field>
390
+ </ExampleSection>
391
+ </ExampleGrid>
392
+
393
+ <ExampleGrid>
394
+ <ExampleSection
395
+ label="Trạng thái Lỗi thủ công"
396
+ description="Tự gắn aria-invalid vào Select."
397
+ codeString={`<Field data-invalid={true} className="w-full">
398
+ <FieldLabel>Dự án</FieldLabel>
399
+ <FieldContent>
400
+ <Select items={{ p1: "Project 1" }}>
401
+ <SelectTrigger aria-invalid={true}>
402
+ <SelectValue placeholder="Chọn dự án..." />
403
+ </SelectTrigger>
404
+ <SelectPortal><SelectContent>
405
+ <SelectItem value="p1">Project 1</SelectItem>
406
+ </SelectContent></SelectPortal>
407
+ </Select>
408
+ </FieldContent>
409
+ <FieldError>Vui lòng chọn một dự án hợp lệ.</FieldError>
410
+ </Field>
411
+ `}
412
+ >
413
+ <Field size={globalSize} data-invalid={true} className="w-full">
414
+ <FieldLabel>Dự án</FieldLabel>
415
+ <FieldContent>
416
+ <Select items={{ p1: "Project 1" }}>
417
+ <SelectTrigger size={globalSize} aria-invalid={true}>
418
+ <SelectValue placeholder="Chọn dự án..." />
419
+ </SelectTrigger>
420
+ <SelectPortal>
421
+ <SelectContent>
422
+ <SelectItem value="p1">Project 1</SelectItem>
423
+ </SelectContent>
424
+ </SelectPortal>
425
+ </Select>
426
+ </FieldContent>
427
+ <FieldError>Vui lòng chọn một dự án hợp lệ.</FieldError>
428
+ </Field>
429
+ </ExampleSection>
430
+
431
+ <ExampleSection
432
+ label="Disabled thủ công"
433
+ description="Khóa SelectTrigger."
434
+ codeString={`<Field className="w-full">
435
+ <FieldLabel>Múi giờ</FieldLabel>
436
+ <FieldContent>
437
+ <Select items={{ gmt: "GMT+7" }}>
438
+ <SelectTrigger disabled>
439
+ <SelectValue placeholder="Chọn múi giờ..." />
440
+ </SelectTrigger>
441
+ <SelectPortal><SelectContent>
442
+ <SelectItem value="gmt">GMT+7 (Indochina Time)</SelectItem>
443
+ </SelectContent></SelectPortal>
444
+ </Select>
445
+ </FieldContent>
446
+ <FieldDescription>
447
+ Múi giờ tự động lấy theo hệ thống.
448
+ </FieldDescription>
449
+ </Field>
450
+ `}
451
+ >
452
+ <Field size={globalSize} className="w-full">
453
+ <FieldLabel>Múi giờ</FieldLabel>
454
+ <FieldContent>
455
+ <Select items={{ gmt: "GMT+7" }}>
456
+ <SelectTrigger size={globalSize} disabled>
457
+ <SelectValue placeholder="Chọn múi giờ..." />
458
+ </SelectTrigger>
459
+ <SelectPortal>
460
+ <SelectContent>
461
+ <SelectItem value="gmt">GMT+7 (Indochina Time)</SelectItem>
462
+ </SelectContent>
463
+ </SelectPortal>
464
+ </Select>
465
+ </FieldContent>
466
+ <FieldDescription>
467
+ Múi giờ tự động lấy theo hệ thống.
468
+ </FieldDescription>
469
+ </Field>
470
+ </ExampleSection>
471
+ </ExampleGrid>
472
+
473
+ <ExampleSection
474
+ label="🧭 Use Case Comparison"
475
+ description="So sánh nhanh khi nào dùng Micro và Macro."
476
+ fullWidth
477
+ codeString={`<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
478
+ {/* Story 1: Macro wins */}
479
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
480
+ <div className="flex items-start gap-3">
481
+ <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
482
+ <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>
483
+ </span>
484
+ <div>
485
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Story 1 · Dùng Macro</p>
486
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">Form nhập Quốc tịch</h3>
487
+ </div>
488
+ </div>
489
+ <p className="text-xs text-muted-foreground leading-relaxed">
490
+ Bạn có 195 quốc gia để chọn, tất cả đều chỉ là chữ. Thay vì viết 195 thẻ <DocsCode>SelectItem</DocsCode>, bạn vứt mảng JSON 195 phần tử đó vào thuộc tính <DocsCode>options</DocsCode> của Macro.
491
+ </p>
492
+ </div>
493
+
494
+ {/* Story 2: Micro wins */}
495
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
496
+ <div className="flex items-start gap-3">
497
+ <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
498
+ <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>
499
+ </span>
500
+ <div>
501
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Story 2 · Dùng Micro</p>
502
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">Menu Chọn Tài khoản</h3>
503
+ </div>
504
+ </div>
505
+ <p className="text-xs text-muted-foreground leading-relaxed">
506
+ Bạn muốn trong danh sách thả xuống, mỗi dòng không chỉ là Tên, mà còn có cả Avatar (ảnh tròn) và Email (chữ mờ ở dưới). Bạn bắt buộc phải dùng Micro để tự thiết kế nội dung bên trong <DocsCode>SelectItem</DocsCode>.
507
+ </p>
508
+ </div>
509
+ </div>
510
+ `}
511
+ >
512
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2">
513
+ {/* Story 1: Macro wins */}
514
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
515
+ <div className="flex items-start gap-3">
516
+ <span className="mt-0.5 shrink-0 rounded-full bg-green-500/10 p-1.5 text-green-600">
517
+ <svg
518
+ xmlns="http://www.w3.org/2000/svg"
519
+ className="size-4"
520
+ viewBox="0 0 24 24"
521
+ fill="none"
522
+ stroke="currentColor"
523
+ strokeWidth="2"
524
+ strokeLinecap="round"
525
+ strokeLinejoin="round"
526
+ aria-hidden="true"
527
+ >
528
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
529
+ </svg>
530
+ </span>
531
+ <div>
532
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
533
+ Story 1 · Dùng Macro
534
+ </p>
535
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
536
+ Form nhập Quốc tịch
537
+ </h3>
538
+ </div>
539
+ </div>
540
+ <p className="text-xs text-muted-foreground leading-relaxed">
541
+ Bạn có 195 quốc gia để chọn, tất cả đều chỉ là chữ. Thay vì viết
542
+ 195 thẻ <DocsCode>SelectItem</DocsCode>, bạn vứt mảng JSON 195
543
+ phần tử đó vào thuộc tính <DocsCode>options</DocsCode> của Macro.
544
+ </p>
545
+ </div>
546
+
547
+ {/* Story 2: Micro wins */}
548
+ <div className="rounded-xl border border-border bg-card p-5 flex flex-col gap-4">
549
+ <div className="flex items-start gap-3">
550
+ <span className="mt-0.5 shrink-0 rounded-full bg-blue-500/10 p-1.5 text-blue-600">
551
+ <svg
552
+ xmlns="http://www.w3.org/2000/svg"
553
+ className="size-4"
554
+ viewBox="0 0 24 24"
555
+ fill="none"
556
+ stroke="currentColor"
557
+ strokeWidth="2"
558
+ strokeLinecap="round"
559
+ strokeLinejoin="round"
560
+ aria-hidden="true"
561
+ >
562
+ <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" />
563
+ </svg>
564
+ </span>
565
+ <div>
566
+ <p className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
567
+ Story 2 · Dùng Micro
568
+ </p>
569
+ <h3 className="mt-0.5 text-sm font-semibold text-foreground">
570
+ Menu Chọn Tài khoản
571
+ </h3>
572
+ </div>
573
+ </div>
574
+ <p className="text-xs text-muted-foreground leading-relaxed">
575
+ Bạn muốn trong danh sách thả xuống, mỗi dòng không chỉ là Tên, mà
576
+ còn có cả Avatar (ảnh tròn) và Email (chữ mờ ở dưới). Bạn bắt buộc
577
+ phải dùng Micro để tự thiết kế nội dung bên trong{" "}
578
+ <DocsCode>SelectItem</DocsCode>.
579
+ </p>
580
+ </div>
581
+ </div>
582
+ </ExampleSection>
583
+ </div>
584
+ );
585
+ }
586
+
587
+ // ──────────────────────────────────────────────────────────
588
+ // SECTION 3: Entry point
589
+ // ──────────────────────────────────────────────────────────
590
+ export default function SelectShowcase() {
591
+ const { size: globalSize } = useDevContext();
592
+ return (
593
+ <Showcase
594
+ title="Select"
595
+ description="Thành phần điều khiển hiển thị danh sách các tùy chọn thả xuống để người dùng chọn."
596
+ generalConcept={
597
+ <ShowcaseDocs>
598
+ <DocsH3>Khi nào nên dùng Macro</DocsH3>
599
+ <DocsP>
600
+ <DocsCode>SelectPreset</DocsCode> đóng gói sẵn cấu trúc 8 thẻ của
601
+ Select nguyên thuỷ thành 1 Component duy nhất. Nó dùng prop{" "}
602
+ <DocsCode>options</DocsCode> để render danh sách thả xuống. Dùng
603
+ Macro cho 90% trường hợp form nhập liệu chọn 1 giá trị thông thường.
604
+ </DocsP>
605
+ <DocsH3>Khi nào nên dùng Micro</DocsH3>
606
+ <DocsP>
607
+ Dùng <DocsCode>Select</DocsCode> và các thành phần con nguyên thuỷ
608
+ khi bạn cần một danh sách thả xuống có phân nhóm (
609
+ <DocsCode>SelectGroup</DocsCode>, <DocsCode>SelectLabel</DocsCode>)
610
+ hoặc khi mỗi tuỳ chọn (<DocsCode>SelectItem</DocsCode>) có thiết kế
611
+ phức tạp (chứa icon, ảnh đại diện, subtext) thay vì chỉ là text đơn
612
+ thuần.
613
+ </DocsP>
614
+ </ShowcaseDocs>
615
+ }
616
+ tabs={[
617
+ {
618
+ label: "Micro (Primitive)",
619
+ content: <SelectMicroShowcase globalSize={globalSize} />,
620
+ },
621
+ {
622
+ label: "Macro (Preset)",
623
+ content: <SelectMacroShowcase globalSize={globalSize} />,
624
+ },
625
+ ]}
626
+ />
627
+ );
628
+ }