shadcn_view_component 0.3.3

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 (507) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +255 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +604 -0
  5. data/app/assets/stylesheets/shadcn-themes.css +1075 -0
  6. data/app/assets/stylesheets/shadcn.css +853 -0
  7. data/app/components/shadcn/accordion/component.rb +44 -0
  8. data/app/components/shadcn/accordion/content/component.rb +44 -0
  9. data/app/components/shadcn/accordion/item/component.rb +41 -0
  10. data/app/components/shadcn/accordion/preview.rb +16 -0
  11. data/app/components/shadcn/accordion/previews/default.html.erb +10 -0
  12. data/app/components/shadcn/accordion/previews/multiple.html.erb +13 -0
  13. data/app/components/shadcn/accordion/trigger/component.rb +52 -0
  14. data/app/components/shadcn/alert/component.rb +52 -0
  15. data/app/components/shadcn/alert/preview.rb +11 -0
  16. data/app/components/shadcn/alert/previews/default.html.erb +8 -0
  17. data/app/components/shadcn/alert.rb +17 -0
  18. data/app/components/shadcn/alert_dialog/action/component.rb +35 -0
  19. data/app/components/shadcn/alert_dialog/cancel/component.rb +16 -0
  20. data/app/components/shadcn/alert_dialog/component.rb +20 -0
  21. data/app/components/shadcn/alert_dialog/content/component.rb +55 -0
  22. data/app/components/shadcn/alert_dialog/header/component.rb +33 -0
  23. data/app/components/shadcn/alert_dialog/preview.rb +16 -0
  24. data/app/components/shadcn/alert_dialog/previews/default.html.erb +13 -0
  25. data/app/components/shadcn/alert_dialog/previews/small_with_media.html.erb +38 -0
  26. data/app/components/shadcn/alert_dialog.rb +32 -0
  27. data/app/components/shadcn/application_view_component.rb +225 -0
  28. data/app/components/shadcn/application_view_component_preview.rb +8 -0
  29. data/app/components/shadcn/aspect_ratio/component.rb +34 -0
  30. data/app/components/shadcn/aspect_ratio/preview.rb +16 -0
  31. data/app/components/shadcn/aspect_ratio/previews/default.html.erb +5 -0
  32. data/app/components/shadcn/aspect_ratio/previews/ratios.html.erb +12 -0
  33. data/app/components/shadcn/attachment/action/component.rb +19 -0
  34. data/app/components/shadcn/attachment/component.rb +76 -0
  35. data/app/components/shadcn/attachment/media/component.rb +56 -0
  36. data/app/components/shadcn/attachment/preview.rb +11 -0
  37. data/app/components/shadcn/attachment/previews/default.html.erb +80 -0
  38. data/app/components/shadcn/attachment/trigger/component.rb +31 -0
  39. data/app/components/shadcn/attachment.rb +42 -0
  40. data/app/components/shadcn/avatar/component.rb +43 -0
  41. data/app/components/shadcn/avatar/fallback/component.rb +23 -0
  42. data/app/components/shadcn/avatar/image/component.rb +20 -0
  43. data/app/components/shadcn/avatar/preview.rb +11 -0
  44. data/app/components/shadcn/avatar/previews/default.html.erb +13 -0
  45. data/app/components/shadcn/avatar.rb +32 -0
  46. data/app/components/shadcn/badge/component.rb +57 -0
  47. data/app/components/shadcn/badge/preview.rb +11 -0
  48. data/app/components/shadcn/badge/previews/default.html.erb +5 -0
  49. data/app/components/shadcn/breadcrumb/component.rb +15 -0
  50. data/app/components/shadcn/breadcrumb/ellipsis/component.rb +28 -0
  51. data/app/components/shadcn/breadcrumb/page/component.rb +25 -0
  52. data/app/components/shadcn/breadcrumb/preview.rb +16 -0
  53. data/app/components/shadcn/breadcrumb/previews/custom_separator.html.erb +17 -0
  54. data/app/components/shadcn/breadcrumb/previews/default.html.erb +15 -0
  55. data/app/components/shadcn/breadcrumb/separator/component.rb +31 -0
  56. data/app/components/shadcn/breadcrumb.rb +18 -0
  57. data/app/components/shadcn/bubble/component.rb +90 -0
  58. data/app/components/shadcn/bubble/preview.rb +16 -0
  59. data/app/components/shadcn/bubble/previews/alignment.html.erb +33 -0
  60. data/app/components/shadcn/bubble/previews/default.html.erb +22 -0
  61. data/app/components/shadcn/bubble/reactions/component.rb +54 -0
  62. data/app/components/shadcn/bubble.rb +24 -0
  63. data/app/components/shadcn/button/component.rb +85 -0
  64. data/app/components/shadcn/button/preview.rb +31 -0
  65. data/app/components/shadcn/button/previews/default.html.erb +8 -0
  66. data/app/components/shadcn/button/previews/sizes.html.erb +5 -0
  67. data/app/components/shadcn/button/previews/variants.html.erb +5 -0
  68. data/app/components/shadcn/button_group/component.rb +53 -0
  69. data/app/components/shadcn/button_group/preview.rb +15 -0
  70. data/app/components/shadcn/button_group/previews/default.html.erb +18 -0
  71. data/app/components/shadcn/button_group/previews/vertical.html.erb +5 -0
  72. data/app/components/shadcn/button_group/separator/component.rb +30 -0
  73. data/app/components/shadcn/button_group/text/component.rb +20 -0
  74. data/app/components/shadcn/calendar/component.rb +558 -0
  75. data/app/components/shadcn/calendar/month.rb +74 -0
  76. data/app/components/shadcn/calendar/preview.rb +64 -0
  77. data/app/components/shadcn/calendar/previews/booked.html.erb +18 -0
  78. data/app/components/shadcn/calendar/previews/custom_cell_size.html.erb +11 -0
  79. data/app/components/shadcn/calendar/previews/date_and_time.html.erb +31 -0
  80. data/app/components/shadcn/calendar/previews/default.html.erb +8 -0
  81. data/app/components/shadcn/calendar/previews/dropdown_caption.html.erb +11 -0
  82. data/app/components/shadcn/calendar/previews/in_a_form.html.erb +8 -0
  83. data/app/components/shadcn/calendar/previews/presets.html.erb +20 -0
  84. data/app/components/shadcn/calendar/previews/range.html.erb +10 -0
  85. data/app/components/shadcn/calendar/previews/week_numbers.html.erb +8 -0
  86. data/app/components/shadcn/card/component.rb +24 -0
  87. data/app/components/shadcn/card/header/component.rb +26 -0
  88. data/app/components/shadcn/card/preview.rb +16 -0
  89. data/app/components/shadcn/card/previews/default.html.erb +18 -0
  90. data/app/components/shadcn/card/previews/image.html.erb +37 -0
  91. data/app/components/shadcn/card.rb +21 -0
  92. data/app/components/shadcn/carousel/component.rb +61 -0
  93. data/app/components/shadcn/carousel/content/component.rb +86 -0
  94. data/app/components/shadcn/carousel/item/component.rb +42 -0
  95. data/app/components/shadcn/carousel/next/component.rb +59 -0
  96. data/app/components/shadcn/carousel/preview.rb +22 -0
  97. data/app/components/shadcn/carousel/previews/default.html.erb +22 -0
  98. data/app/components/shadcn/carousel/previews/sizes.html.erb +42 -0
  99. data/app/components/shadcn/carousel/previews/vertical.html.erb +27 -0
  100. data/app/components/shadcn/carousel/previous/component.rb +59 -0
  101. data/app/components/shadcn/chart/area/component.rb +43 -0
  102. data/app/components/shadcn/chart/bar/component.rb +75 -0
  103. data/app/components/shadcn/chart/cartesian/component.rb +152 -0
  104. data/app/components/shadcn/chart/component.rb +124 -0
  105. data/app/components/shadcn/chart/focusable.rb +38 -0
  106. data/app/components/shadcn/chart/legend/component.rb +55 -0
  107. data/app/components/shadcn/chart/line/component.rb +50 -0
  108. data/app/components/shadcn/chart/pie/component.rb +169 -0
  109. data/app/components/shadcn/chart/plot.rb +147 -0
  110. data/app/components/shadcn/chart/preview.rb +45 -0
  111. data/app/components/shadcn/chart/previews/area.html.erb +31 -0
  112. data/app/components/shadcn/chart/previews/bar.html.erb +32 -0
  113. data/app/components/shadcn/chart/previews/bar_stacked.html.erb +30 -0
  114. data/app/components/shadcn/chart/previews/default.html.erb +30 -0
  115. data/app/components/shadcn/chart/previews/donut.html.erb +16 -0
  116. data/app/components/shadcn/chart/previews/line.html.erb +30 -0
  117. data/app/components/shadcn/chart/previews/percentages.html.erb +17 -0
  118. data/app/components/shadcn/chart/table/component.rb +75 -0
  119. data/app/components/shadcn/chart/tooltip/component.rb +111 -0
  120. data/app/components/shadcn/checkbox/component.rb +109 -0
  121. data/app/components/shadcn/checkbox/preview.rb +16 -0
  122. data/app/components/shadcn/checkbox/previews/default.html.erb +14 -0
  123. data/app/components/shadcn/checkbox/previews/states.html.erb +23 -0
  124. data/app/components/shadcn/collapsible/component.rb +35 -0
  125. data/app/components/shadcn/collapsible/content/component.rb +20 -0
  126. data/app/components/shadcn/collapsible/preview.rb +11 -0
  127. data/app/components/shadcn/collapsible/previews/default.html.erb +9 -0
  128. data/app/components/shadcn/collapsible/trigger/component.rb +23 -0
  129. data/app/components/shadcn/combobox/chip/component.rb +60 -0
  130. data/app/components/shadcn/combobox/chip_input/component.rb +43 -0
  131. data/app/components/shadcn/combobox/chips/component.rb +54 -0
  132. data/app/components/shadcn/combobox/clear/component.rb +32 -0
  133. data/app/components/shadcn/combobox/component.rb +113 -0
  134. data/app/components/shadcn/combobox/content/component.rb +59 -0
  135. data/app/components/shadcn/combobox/empty/component.rb +23 -0
  136. data/app/components/shadcn/combobox/input/component.rb +85 -0
  137. data/app/components/shadcn/combobox/item/component.rb +69 -0
  138. data/app/components/shadcn/combobox/list/component.rb +27 -0
  139. data/app/components/shadcn/combobox/preview.rb +31 -0
  140. data/app/components/shadcn/combobox/previews/default.html.erb +20 -0
  141. data/app/components/shadcn/combobox/previews/grouped.html.erb +25 -0
  142. data/app/components/shadcn/combobox/previews/multiple.html.erb +28 -0
  143. data/app/components/shadcn/combobox/previews/with_clear.html.erb +16 -0
  144. data/app/components/shadcn/combobox/trigger/component.rb +54 -0
  145. data/app/components/shadcn/combobox.rb +16 -0
  146. data/app/components/shadcn/command/component.rb +67 -0
  147. data/app/components/shadcn/command/dialog/component.rb +72 -0
  148. data/app/components/shadcn/command/empty/component.rb +29 -0
  149. data/app/components/shadcn/command/group/component.rb +63 -0
  150. data/app/components/shadcn/command/input/component.rb +66 -0
  151. data/app/components/shadcn/command/item/component.rb +62 -0
  152. data/app/components/shadcn/command/list/component.rb +36 -0
  153. data/app/components/shadcn/command/preview.rb +26 -0
  154. data/app/components/shadcn/command/previews/default.html.erb +41 -0
  155. data/app/components/shadcn/command/previews/dialog.html.erb +33 -0
  156. data/app/components/shadcn/command/previews/ranking.html.erb +16 -0
  157. data/app/components/shadcn/command/separator/component.rb +33 -0
  158. data/app/components/shadcn/command.rb +14 -0
  159. data/app/components/shadcn/concerns/modal_root.rb +43 -0
  160. data/app/components/shadcn/concerns/submits_value.rb +81 -0
  161. data/app/components/shadcn/context_menu/component.rb +45 -0
  162. data/app/components/shadcn/context_menu/content/component.rb +40 -0
  163. data/app/components/shadcn/context_menu/preview.rb +16 -0
  164. data/app/components/shadcn/context_menu/previews/default.html.erb +34 -0
  165. data/app/components/shadcn/context_menu/previews/items.html.erb +35 -0
  166. data/app/components/shadcn/context_menu/sub/component.rb +47 -0
  167. data/app/components/shadcn/context_menu/sub_content/component.rb +31 -0
  168. data/app/components/shadcn/context_menu/trigger/component.rb +50 -0
  169. data/app/components/shadcn/context_menu.rb +43 -0
  170. data/app/components/shadcn/dialog/close/component.rb +20 -0
  171. data/app/components/shadcn/dialog/component.rb +20 -0
  172. data/app/components/shadcn/dialog/content/component.rb +78 -0
  173. data/app/components/shadcn/dialog/header/component.rb +23 -0
  174. data/app/components/shadcn/dialog/overlay/component.rb +28 -0
  175. data/app/components/shadcn/dialog/preview.rb +28 -0
  176. data/app/components/shadcn/dialog/previews/default.html.erb +17 -0
  177. data/app/components/shadcn/dialog/previews/inside_stacking_context.html.erb +25 -0
  178. data/app/components/shadcn/dialog/previews/no_close_button.html.erb +15 -0
  179. data/app/components/shadcn/dialog/previews/scrollable_content.html.erb +29 -0
  180. data/app/components/shadcn/dialog/trigger/component.rb +24 -0
  181. data/app/components/shadcn/dialog.rb +17 -0
  182. data/app/components/shadcn/drawer/component.rb +33 -0
  183. data/app/components/shadcn/drawer/content/component.rb +95 -0
  184. data/app/components/shadcn/drawer/header/component.rb +34 -0
  185. data/app/components/shadcn/drawer/preview.rb +29 -0
  186. data/app/components/shadcn/drawer/previews/default.html.erb +21 -0
  187. data/app/components/shadcn/drawer/previews/scrollable.html.erb +20 -0
  188. data/app/components/shadcn/drawer/previews/scrollable_side.html.erb +21 -0
  189. data/app/components/shadcn/drawer/previews/sides.html.erb +17 -0
  190. data/app/components/shadcn/drawer.rb +27 -0
  191. data/app/components/shadcn/dropdown_menu/checkbox_item/component.rb +61 -0
  192. data/app/components/shadcn/dropdown_menu/component.rb +48 -0
  193. data/app/components/shadcn/dropdown_menu/content/component.rb +49 -0
  194. data/app/components/shadcn/dropdown_menu/group/component.rb +16 -0
  195. data/app/components/shadcn/dropdown_menu/item/component.rb +50 -0
  196. data/app/components/shadcn/dropdown_menu/preview.rb +16 -0
  197. data/app/components/shadcn/dropdown_menu/previews/checkboxes_and_radio.html.erb +34 -0
  198. data/app/components/shadcn/dropdown_menu/previews/default.html.erb +23 -0
  199. data/app/components/shadcn/dropdown_menu/radio_group/component.rb +16 -0
  200. data/app/components/shadcn/dropdown_menu/radio_item/component.rb +63 -0
  201. data/app/components/shadcn/dropdown_menu/sub/component.rb +44 -0
  202. data/app/components/shadcn/dropdown_menu/sub_content/component.rb +45 -0
  203. data/app/components/shadcn/dropdown_menu/sub_trigger/component.rb +58 -0
  204. data/app/components/shadcn/dropdown_menu/trigger/component.rb +25 -0
  205. data/app/components/shadcn/dropdown_menu.rb +18 -0
  206. data/app/components/shadcn/empty/component.rb +17 -0
  207. data/app/components/shadcn/empty/media/component.rb +48 -0
  208. data/app/components/shadcn/empty/preview.rb +16 -0
  209. data/app/components/shadcn/empty/previews/default.html.erb +15 -0
  210. data/app/components/shadcn/empty/previews/media.html.erb +32 -0
  211. data/app/components/shadcn/empty.rb +26 -0
  212. data/app/components/shadcn/field/component.rb +61 -0
  213. data/app/components/shadcn/field/error/component.rb +49 -0
  214. data/app/components/shadcn/field/legend/component.rb +30 -0
  215. data/app/components/shadcn/field/preview.rb +17 -0
  216. data/app/components/shadcn/field/previews/default.html.erb +29 -0
  217. data/app/components/shadcn/field/previews/form_builder.html.erb +38 -0
  218. data/app/components/shadcn/field/separator/component.rb +35 -0
  219. data/app/components/shadcn/field.rb +44 -0
  220. data/app/components/shadcn/hover_card/component.rb +51 -0
  221. data/app/components/shadcn/hover_card/content/component.rb +45 -0
  222. data/app/components/shadcn/hover_card/preview.rb +16 -0
  223. data/app/components/shadcn/hover_card/previews/default.html.erb +36 -0
  224. data/app/components/shadcn/hover_card/previews/sides.html.erb +15 -0
  225. data/app/components/shadcn/hover_card/trigger/component.rb +33 -0
  226. data/app/components/shadcn/icon/component.rb +76 -0
  227. data/app/components/shadcn/icon.rb +43 -0
  228. data/app/components/shadcn/input/component.rb +26 -0
  229. data/app/components/shadcn/input/preview.rb +16 -0
  230. data/app/components/shadcn/input/previews/default.html.erb +5 -0
  231. data/app/components/shadcn/input/previews/states.html.erb +20 -0
  232. data/app/components/shadcn/input_group/addon/component.rb +65 -0
  233. data/app/components/shadcn/input_group/button/component.rb +40 -0
  234. data/app/components/shadcn/input_group/component.rb +43 -0
  235. data/app/components/shadcn/input_group/input/component.rb +25 -0
  236. data/app/components/shadcn/input_group/preview.rb +17 -0
  237. data/app/components/shadcn/input_group/previews/addons.html.erb +53 -0
  238. data/app/components/shadcn/input_group/previews/default.html.erb +25 -0
  239. data/app/components/shadcn/input_group/text/component.rb +20 -0
  240. data/app/components/shadcn/input_group/textarea/component.rb +21 -0
  241. data/app/components/shadcn/input_otp/component.rb +95 -0
  242. data/app/components/shadcn/input_otp/preview.rb +17 -0
  243. data/app/components/shadcn/input_otp/previews/default.html.erb +19 -0
  244. data/app/components/shadcn/input_otp/previews/variations.html.erb +33 -0
  245. data/app/components/shadcn/input_otp/separator/component.rb +21 -0
  246. data/app/components/shadcn/input_otp/slot/component.rb +60 -0
  247. data/app/components/shadcn/input_otp.rb +11 -0
  248. data/app/components/shadcn/item/component.rb +56 -0
  249. data/app/components/shadcn/item/group/component.rb +53 -0
  250. data/app/components/shadcn/item/media/component.rb +53 -0
  251. data/app/components/shadcn/item/preview.rb +20 -0
  252. data/app/components/shadcn/item/previews/default.html.erb +32 -0
  253. data/app/components/shadcn/item/previews/link.html.erb +39 -0
  254. data/app/components/shadcn/item/previews/outline.html.erb +8 -0
  255. data/app/components/shadcn/item/separator/component.rb +24 -0
  256. data/app/components/shadcn/item.rb +34 -0
  257. data/app/components/shadcn/kbd/component.rb +23 -0
  258. data/app/components/shadcn/kbd/group/component.rb +17 -0
  259. data/app/components/shadcn/kbd/preview.rb +11 -0
  260. data/app/components/shadcn/kbd/previews/default.html.erb +4 -0
  261. data/app/components/shadcn/label/component.rb +20 -0
  262. data/app/components/shadcn/label/preview.rb +11 -0
  263. data/app/components/shadcn/label/previews/default.html.erb +4 -0
  264. data/app/components/shadcn/marker/component.rb +46 -0
  265. data/app/components/shadcn/marker/icon/component.rb +23 -0
  266. data/app/components/shadcn/marker/preview.rb +17 -0
  267. data/app/components/shadcn/marker/previews/default.html.erb +18 -0
  268. data/app/components/shadcn/marker/previews/status.html.erb +32 -0
  269. data/app/components/shadcn/marker.rb +17 -0
  270. data/app/components/shadcn/menubar/component.rb +36 -0
  271. data/app/components/shadcn/menubar/content/component.rb +49 -0
  272. data/app/components/shadcn/menubar/menu/component.rb +39 -0
  273. data/app/components/shadcn/menubar/preview.rb +16 -0
  274. data/app/components/shadcn/menubar/previews/default.html.erb +52 -0
  275. data/app/components/shadcn/menubar/previews/items.html.erb +38 -0
  276. data/app/components/shadcn/menubar/sub/component.rb +43 -0
  277. data/app/components/shadcn/menubar/sub_content/component.rb +31 -0
  278. data/app/components/shadcn/menubar/sub_trigger/component.rb +31 -0
  279. data/app/components/shadcn/menubar/trigger/component.rb +41 -0
  280. data/app/components/shadcn/menubar.rb +47 -0
  281. data/app/components/shadcn/message/component.rb +33 -0
  282. data/app/components/shadcn/message/preview.rb +16 -0
  283. data/app/components/shadcn/message/previews/actions.html.erb +51 -0
  284. data/app/components/shadcn/message/previews/default.html.erb +35 -0
  285. data/app/components/shadcn/message.rb +35 -0
  286. data/app/components/shadcn/message_scroller/button/component.rb +78 -0
  287. data/app/components/shadcn/message_scroller/component.rb +59 -0
  288. data/app/components/shadcn/message_scroller/content/component.rb +50 -0
  289. data/app/components/shadcn/message_scroller/item/component.rb +45 -0
  290. data/app/components/shadcn/message_scroller/preview.rb +11 -0
  291. data/app/components/shadcn/message_scroller/previews/default.html.erb +72 -0
  292. data/app/components/shadcn/message_scroller/viewport/component.rb +41 -0
  293. data/app/components/shadcn/mode_switcher/component.rb +67 -0
  294. data/app/components/shadcn/mode_switcher/preview.rb +11 -0
  295. data/app/components/shadcn/mode_switcher/previews/default.html.erb +5 -0
  296. data/app/components/shadcn/mode_toggle/component.rb +75 -0
  297. data/app/components/shadcn/mode_toggle/preview.rb +11 -0
  298. data/app/components/shadcn/mode_toggle/previews/default.html.erb +20 -0
  299. data/app/components/shadcn/native_select/component.rb +59 -0
  300. data/app/components/shadcn/native_select/preview.rb +16 -0
  301. data/app/components/shadcn/native_select/previews/default.html.erb +9 -0
  302. data/app/components/shadcn/native_select/previews/groups.html.erb +26 -0
  303. data/app/components/shadcn/native_select.rb +16 -0
  304. data/app/components/shadcn/navigation_menu/component.rb +51 -0
  305. data/app/components/shadcn/navigation_menu/content/component.rb +58 -0
  306. data/app/components/shadcn/navigation_menu/preview.rb +11 -0
  307. data/app/components/shadcn/navigation_menu/previews/default.html.erb +49 -0
  308. data/app/components/shadcn/navigation_menu/trigger/component.rb +59 -0
  309. data/app/components/shadcn/navigation_menu.rb +28 -0
  310. data/app/components/shadcn/pagination/component.rb +19 -0
  311. data/app/components/shadcn/pagination/ellipsis/component.rb +28 -0
  312. data/app/components/shadcn/pagination/link/component.rb +37 -0
  313. data/app/components/shadcn/pagination/next/component.rb +31 -0
  314. data/app/components/shadcn/pagination/preview.rb +16 -0
  315. data/app/components/shadcn/pagination/previews/default.html.erb +18 -0
  316. data/app/components/shadcn/pagination/previews/simple.html.erb +39 -0
  317. data/app/components/shadcn/pagination/previous/component.rb +31 -0
  318. data/app/components/shadcn/pagination.rb +14 -0
  319. data/app/components/shadcn/parts.rb +38 -0
  320. data/app/components/shadcn/popover/anchor/component.rb +17 -0
  321. data/app/components/shadcn/popover/component.rb +42 -0
  322. data/app/components/shadcn/popover/content/component.rb +40 -0
  323. data/app/components/shadcn/popover/preview.rb +28 -0
  324. data/app/components/shadcn/popover/previews/align.html.erb +13 -0
  325. data/app/components/shadcn/popover/previews/default.html.erb +9 -0
  326. data/app/components/shadcn/popover/previews/inside_containing_block.html.erb +41 -0
  327. data/app/components/shadcn/popover/previews/inside_stacking_context.html.erb +30 -0
  328. data/app/components/shadcn/popover/trigger/component.rb +24 -0
  329. data/app/components/shadcn/popover.rb +16 -0
  330. data/app/components/shadcn/progress/component.rb +62 -0
  331. data/app/components/shadcn/progress/preview.rb +11 -0
  332. data/app/components/shadcn/progress/previews/default.html.erb +5 -0
  333. data/app/components/shadcn/radio_group/component.rb +51 -0
  334. data/app/components/shadcn/radio_group/item/component.rb +74 -0
  335. data/app/components/shadcn/radio_group/preview.rb +16 -0
  336. data/app/components/shadcn/radio_group/previews/default.html.erb +15 -0
  337. data/app/components/shadcn/radio_group/previews/states.html.erb +41 -0
  338. data/app/components/shadcn/resizable/component.rb +59 -0
  339. data/app/components/shadcn/resizable/handle/component.rb +70 -0
  340. data/app/components/shadcn/resizable/panel/component.rb +53 -0
  341. data/app/components/shadcn/resizable/preview.rb +23 -0
  342. data/app/components/shadcn/resizable/previews/default.html.erb +25 -0
  343. data/app/components/shadcn/resizable/previews/vertical.html.erb +19 -0
  344. data/app/components/shadcn/resizable/previews/with_handle.html.erb +17 -0
  345. data/app/components/shadcn/scroll_area/component.rb +84 -0
  346. data/app/components/shadcn/scroll_area/preview.rb +11 -0
  347. data/app/components/shadcn/scroll_area/previews/default.html.erb +36 -0
  348. data/app/components/shadcn/scroll_area/scrollbar/component.rb +72 -0
  349. data/app/components/shadcn/scroll_area/viewport/component.rb +70 -0
  350. data/app/components/shadcn/scroll_area.rb +14 -0
  351. data/app/components/shadcn/select/component.rb +67 -0
  352. data/app/components/shadcn/select/content/component.rb +157 -0
  353. data/app/components/shadcn/select/empty/component.rb +38 -0
  354. data/app/components/shadcn/select/group/component.rb +16 -0
  355. data/app/components/shadcn/select/item/component.rb +71 -0
  356. data/app/components/shadcn/select/list/component.rb +41 -0
  357. data/app/components/shadcn/select/preview.rb +24 -0
  358. data/app/components/shadcn/select/previews/default.html.erb +17 -0
  359. data/app/components/shadcn/select/previews/scrollable.html.erb +19 -0
  360. data/app/components/shadcn/select/previews/searchable.html.erb +18 -0
  361. data/app/components/shadcn/select/previews/states.html.erb +25 -0
  362. data/app/components/shadcn/select/search/component.rb +54 -0
  363. data/app/components/shadcn/select/trigger/component.rb +78 -0
  364. data/app/components/shadcn/select/value/component.rb +28 -0
  365. data/app/components/shadcn/select.rb +15 -0
  366. data/app/components/shadcn/separator/component.rb +41 -0
  367. data/app/components/shadcn/separator/preview.rb +11 -0
  368. data/app/components/shadcn/separator/previews/default.html.erb +9 -0
  369. data/app/components/shadcn/sheet/component.rb +16 -0
  370. data/app/components/shadcn/sheet/content/component.rb +98 -0
  371. data/app/components/shadcn/sheet/header/component.rb +23 -0
  372. data/app/components/shadcn/sheet/preview.rb +16 -0
  373. data/app/components/shadcn/sheet/previews/default.html.erb +16 -0
  374. data/app/components/shadcn/sheet/previews/no_close_button.html.erb +14 -0
  375. data/app/components/shadcn/sheet.rb +22 -0
  376. data/app/components/shadcn/sidebar/component.rb +232 -0
  377. data/app/components/shadcn/sidebar/input/component.rb +25 -0
  378. data/app/components/shadcn/sidebar/menu_action/component.rb +58 -0
  379. data/app/components/shadcn/sidebar/menu_button/component.rb +100 -0
  380. data/app/components/shadcn/sidebar/menu_skeleton/component.rb +51 -0
  381. data/app/components/shadcn/sidebar/menu_sub_button/component.rb +60 -0
  382. data/app/components/shadcn/sidebar/preview.rb +22 -0
  383. data/app/components/shadcn/sidebar/previews/default.html.erb +189 -0
  384. data/app/components/shadcn/sidebar/previews/floating.html.erb +39 -0
  385. data/app/components/shadcn/sidebar/previews/inset.html.erb +48 -0
  386. data/app/components/shadcn/sidebar/provider/component.rb +53 -0
  387. data/app/components/shadcn/sidebar/rail/component.rb +43 -0
  388. data/app/components/shadcn/sidebar/separator/component.rb +23 -0
  389. data/app/components/shadcn/sidebar/trigger/component.rb +39 -0
  390. data/app/components/shadcn/sidebar.rb +98 -0
  391. data/app/components/shadcn/skeleton/component.rb +14 -0
  392. data/app/components/shadcn/skeleton/preview.rb +11 -0
  393. data/app/components/shadcn/skeleton/previews/default.html.erb +7 -0
  394. data/app/components/shadcn/slider/component.rb +145 -0
  395. data/app/components/shadcn/slider/preview.rb +16 -0
  396. data/app/components/shadcn/slider/previews/default.html.erb +17 -0
  397. data/app/components/shadcn/slider/previews/vertical.html.erb +7 -0
  398. data/app/components/shadcn/slider/range/component.rb +51 -0
  399. data/app/components/shadcn/slider/thumb/component.rb +58 -0
  400. data/app/components/shadcn/slider/track/component.rb +32 -0
  401. data/app/components/shadcn/spinner/component.rb +21 -0
  402. data/app/components/shadcn/spinner/preview.rb +11 -0
  403. data/app/components/shadcn/spinner/previews/default.html.erb +7 -0
  404. data/app/components/shadcn/switch/component.rb +104 -0
  405. data/app/components/shadcn/switch/preview.rb +11 -0
  406. data/app/components/shadcn/switch/previews/default.html.erb +24 -0
  407. data/app/components/shadcn/table/component.rb +26 -0
  408. data/app/components/shadcn/table/preview.rb +16 -0
  409. data/app/components/shadcn/table/previews/default.html.erb +19 -0
  410. data/app/components/shadcn/table/previews/footer.html.erb +25 -0
  411. data/app/components/shadcn/table.rb +33 -0
  412. data/app/components/shadcn/tabs/component.rb +40 -0
  413. data/app/components/shadcn/tabs/content/component.rb +34 -0
  414. data/app/components/shadcn/tabs/list/component.rb +51 -0
  415. data/app/components/shadcn/tabs/preview.rb +16 -0
  416. data/app/components/shadcn/tabs/previews/default.html.erb +21 -0
  417. data/app/components/shadcn/tabs/previews/line.html.erb +23 -0
  418. data/app/components/shadcn/tabs/trigger/component.rb +66 -0
  419. data/app/components/shadcn/textarea/component.rb +24 -0
  420. data/app/components/shadcn/textarea/preview.rb +16 -0
  421. data/app/components/shadcn/textarea/previews/default.html.erb +3 -0
  422. data/app/components/shadcn/textarea/previews/states.html.erb +18 -0
  423. data/app/components/shadcn/theme_selector/component.rb +88 -0
  424. data/app/components/shadcn/theme_selector/preview.rb +17 -0
  425. data/app/components/shadcn/theme_selector/previews/all_themes.html.erb +20 -0
  426. data/app/components/shadcn/theme_selector/previews/default.html.erb +18 -0
  427. data/app/components/shadcn/toaster/component.rb +139 -0
  428. data/app/components/shadcn/toaster/preview.rb +16 -0
  429. data/app/components/shadcn/toaster/previews/default.html.erb +19 -0
  430. data/app/components/shadcn/toaster/previews/from_the_server.html.erb +15 -0
  431. data/app/components/shadcn/toaster/toast/component.rb +134 -0
  432. data/app/components/shadcn/toggle/component.rb +81 -0
  433. data/app/components/shadcn/toggle/preview.rb +11 -0
  434. data/app/components/shadcn/toggle/previews/default.html.erb +6 -0
  435. data/app/components/shadcn/toggle_group/component.rb +62 -0
  436. data/app/components/shadcn/toggle_group/item/component.rb +59 -0
  437. data/app/components/shadcn/toggle_group/preview.rb +16 -0
  438. data/app/components/shadcn/toggle_group/previews/default.html.erb +12 -0
  439. data/app/components/shadcn/toggle_group/previews/sizes.html.erb +37 -0
  440. data/app/components/shadcn/tooltip/component.rb +38 -0
  441. data/app/components/shadcn/tooltip/content/component.rb +62 -0
  442. data/app/components/shadcn/tooltip/preview.rb +21 -0
  443. data/app/components/shadcn/tooltip/previews/default.html.erb +4 -0
  444. data/app/components/shadcn/tooltip/previews/sides.html.erb +19 -0
  445. data/app/components/shadcn/tooltip/previews/with_keyboard_shortcut.html.erb +11 -0
  446. data/app/components/shadcn/tooltip/provider/component.rb +28 -0
  447. data/app/components/shadcn/tooltip/trigger/component.rb +25 -0
  448. data/app/helpers/shadcn_view_component/form_helper.rb +25 -0
  449. data/app/helpers/shadcn_view_component/theme_helper.rb +61 -0
  450. data/app/javascript/shadcn/animation.js +180 -0
  451. data/app/javascript/shadcn/command_score.js +110 -0
  452. data/app/javascript/shadcn/controllers/accordion_controller.js +127 -0
  453. data/app/javascript/shadcn/controllers/avatar_controller.js +32 -0
  454. data/app/javascript/shadcn/controllers/calendar_controller.js +633 -0
  455. data/app/javascript/shadcn/controllers/carousel_controller.js +139 -0
  456. data/app/javascript/shadcn/controllers/chart_controller.js +110 -0
  457. data/app/javascript/shadcn/controllers/checkbox_controller.js +61 -0
  458. data/app/javascript/shadcn/controllers/collapsible_controller.js +55 -0
  459. data/app/javascript/shadcn/controllers/combobox_controller.js +360 -0
  460. data/app/javascript/shadcn/controllers/command_controller.js +199 -0
  461. data/app/javascript/shadcn/controllers/dialog_controller.js +154 -0
  462. data/app/javascript/shadcn/controllers/drawer_controller.js +265 -0
  463. data/app/javascript/shadcn/controllers/dropdown_menu_controller.js +259 -0
  464. data/app/javascript/shadcn/controllers/hover_card_controller.js +85 -0
  465. data/app/javascript/shadcn/controllers/input_group_controller.js +17 -0
  466. data/app/javascript/shadcn/controllers/input_otp_controller.js +80 -0
  467. data/app/javascript/shadcn/controllers/menubar_controller.js +151 -0
  468. data/app/javascript/shadcn/controllers/message_scroller_controller.js +456 -0
  469. data/app/javascript/shadcn/controllers/navigation_menu_controller.js +211 -0
  470. data/app/javascript/shadcn/controllers/popover_controller.js +66 -0
  471. data/app/javascript/shadcn/controllers/radio_group_controller.js +69 -0
  472. data/app/javascript/shadcn/controllers/resizable_controller.js +167 -0
  473. data/app/javascript/shadcn/controllers/scroll_area_controller.js +253 -0
  474. data/app/javascript/shadcn/controllers/select_controller.js +320 -0
  475. data/app/javascript/shadcn/controllers/sidebar_controller.js +273 -0
  476. data/app/javascript/shadcn/controllers/slider_controller.js +230 -0
  477. data/app/javascript/shadcn/controllers/switch_controller.js +39 -0
  478. data/app/javascript/shadcn/controllers/tabs_controller.js +81 -0
  479. data/app/javascript/shadcn/controllers/theme_controller.js +67 -0
  480. data/app/javascript/shadcn/controllers/toaster_controller.js +281 -0
  481. data/app/javascript/shadcn/controllers/toggle_controller.js +24 -0
  482. data/app/javascript/shadcn/controllers/toggle_group_controller.js +73 -0
  483. data/app/javascript/shadcn/controllers/tooltip_controller.js +58 -0
  484. data/app/javascript/shadcn/direction.js +41 -0
  485. data/app/javascript/shadcn/dismiss.js +73 -0
  486. data/app/javascript/shadcn/floating.js +207 -0
  487. data/app/javascript/shadcn/focus.js +86 -0
  488. data/app/javascript/shadcn/id.js +14 -0
  489. data/app/javascript/shadcn/index.js +110 -0
  490. data/app/javascript/shadcn/popper.js +262 -0
  491. data/app/javascript/shadcn/scroll_geometry.js +267 -0
  492. data/app/javascript/shadcn/theme.js +161 -0
  493. data/app/javascript/shadcn/top_layer.js +59 -0
  494. data/app/javascript/shadcn/typeahead.js +99 -0
  495. data/config/importmap.rb +6 -0
  496. data/config/locales/en.yml +62 -0
  497. data/lib/generators/shadcn_view_component/install/install_generator.rb +149 -0
  498. data/lib/shadcn_view_component/engine.rb +73 -0
  499. data/lib/shadcn_view_component/form_builder.rb +264 -0
  500. data/lib/shadcn_view_component/icon_registry.rb +66 -0
  501. data/lib/shadcn_view_component/icons.rb +32 -0
  502. data/lib/shadcn_view_component/themes.rb +1065 -0
  503. data/lib/shadcn_view_component/version.rb +3 -0
  504. data/lib/shadcn_view_component.rb +82 -0
  505. data/lib/tasks/icons.rake +53 -0
  506. data/lib/tasks/themes.rake +171 -0
  507. metadata +608 -0
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Chart
5
+ module Tooltip
6
+ # `ChartTooltipContent`, 1:1 in markup.
7
+ #
8
+ # Upstream's is rendered by recharts each time the pointer moves, with the
9
+ # hovered item's payload. Here it is rendered once, empty, and the
10
+ # controller writes the label, the name, the value and the indicator's
11
+ # colour into it — which is the same DOM, arrived at from the other side.
12
+ #
13
+ # `indicator:` is upstream's `dot | line | dashed`, and the classes for
14
+ # all three come from `chart.tsx`.
15
+ class Component < ApplicationViewComponent
16
+ INDICATORS = {
17
+ dot: "h-2.5 w-2.5",
18
+ line: "w-1",
19
+ dashed: "w-0 border-[1.5px] border-dashed bg-transparent"
20
+ }.freeze
21
+
22
+ default_tag :div
23
+ slot_name :"chart-tooltip"
24
+
25
+ style do
26
+ base {
27
+ "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background " \
28
+ "px-2.5 py-1.5 text-xs shadow-xl"
29
+ }
30
+ end
31
+
32
+ attr_reader :indicator, :hide_label, :hide_indicator
33
+
34
+ def initialize(indicator: :dot, hide_label: false, hide_indicator: false, **attributes)
35
+ @indicator = INDICATORS.key?(indicator&.to_sym) ? indicator.to_sym : :dot
36
+ @hide_label = hide_label
37
+ @hide_indicator = hide_indicator
38
+ super(**attributes)
39
+ end
40
+
41
+ def element_attributes(**defaults)
42
+ super(**{
43
+ "data-shadcn--chart-target" => "tooltip",
44
+ hidden: true,
45
+ # Positioned against the container rather than by the wrapper
46
+ # recharts renders and this port does not.
47
+ style: merged_style("position:absolute;pointer-events:none")
48
+ }.merge(defaults))
49
+ end
50
+
51
+ def call
52
+ render_element(body: safe_join([ (heading unless nest_label?), items ].compact))
53
+ end
54
+
55
+ private
56
+
57
+ # Upstream's `nestLabel`: with a single item and an indicator that is
58
+ # not a dot, the label moves *inside* the row and the row bottom-aligns
59
+ # (`chart.tsx:186`). A pie's tooltip is always a single item, so here it
60
+ # is decided by the indicator alone.
61
+ def nest_label? = !hide_label && indicator != :dot
62
+
63
+ def heading
64
+ return if hide_label
65
+
66
+ tag.div(class: "font-medium", "data-shadcn--chart-target": "label")
67
+ end
68
+
69
+ def items
70
+ tag.div(class: "grid gap-1.5") do
71
+ tag.div(class: row_classes) do
72
+ safe_join([ swatch, body ].compact)
73
+ end
74
+ end
75
+ end
76
+
77
+ def row_classes
78
+ [
79
+ "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
80
+ ("items-center" if indicator == :dot)
81
+ ].compact.join(" ")
82
+ end
83
+
84
+ def swatch
85
+ return if hide_indicator
86
+
87
+ classes = [
88
+ "shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
89
+ INDICATORS[indicator],
90
+ ("my-0.5" if nest_label? && indicator == :dashed)
91
+ ].compact.join(" ")
92
+
93
+ tag.div(class: classes, "data-shadcn--chart-target": "indicator")
94
+ end
95
+
96
+ def body
97
+ tag.div(class: "flex flex-1 #{nest_label? ? 'items-end' : 'items-center'} justify-between leading-none") do
98
+ safe_join([
99
+ tag.div(class: "grid gap-1.5") do
100
+ safe_join([ (heading if nest_label?),
101
+ tag.span(class: "text-muted-foreground", "data-shadcn--chart-target": "name") ].compact)
102
+ end,
103
+ tag.span(class: "font-mono font-medium text-foreground tabular-nums",
104
+ "data-shadcn--chart-target": "value")
105
+ ])
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Checkbox
5
+ # Port of registry/new-york-v4/ui/checkbox.tsx
6
+ #
7
+ # Like Radix, this renders a `role="checkbox"` button and — when `name:` is
8
+ # given — a visually hidden native checkbox next to it so the control takes
9
+ # part in normal form submission.
10
+ class Component < ApplicationViewComponent
11
+ INDICATOR_CLASSES = "grid place-content-center text-current transition-none"
12
+
13
+ # Radix's BubbleInput styling: present for the form, invisible to the user.
14
+ HIDDEN_INPUT_STYLE = "transform:translateX(-100%);position:absolute;" \
15
+ "pointer-events:none;opacity:0;margin:0"
16
+
17
+ default_tag :button
18
+ slot_name :checkbox
19
+
20
+ style do
21
+ base {
22
+ "peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs " \
23
+ "transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] " \
24
+ "focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 " \
25
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 " \
26
+ "data-[state=checked]:border-primary data-[state=checked]:bg-primary " \
27
+ "data-[state=checked]:text-primary-foreground dark:bg-input/30 " \
28
+ "dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary"
29
+ }
30
+ end
31
+
32
+ attr_reader :name, :value, :checked, :indeterminate, :disabled
33
+
34
+ def initialize(name: nil, value: "on", checked: false, indeterminate: false,
35
+ disabled: false, **attributes)
36
+ @name = name
37
+ @value = value
38
+ @checked = checked
39
+ @indeterminate = indeterminate
40
+ @disabled = disabled
41
+ super(**attributes)
42
+ end
43
+
44
+ def state
45
+ return "indeterminate" if indeterminate
46
+
47
+ checked ? "checked" : "unchecked"
48
+ end
49
+
50
+ def input_id
51
+ @input_id ||= "shadcn-checkbox-#{SecureRandom.hex(4)}" if name
52
+ end
53
+
54
+ def element_attributes(**defaults)
55
+ super(**{
56
+ type: "button",
57
+ role: "checkbox",
58
+ value: value,
59
+ disabled: (true if disabled),
60
+ "aria-checked" => (state == "indeterminate" ? "mixed" : checked.to_s),
61
+ "data-state" => state,
62
+ "data-disabled" => (true if disabled),
63
+ "data-controller" => "shadcn--checkbox",
64
+ "data-shadcn--checkbox-checked-value" => checked,
65
+ "data-shadcn--checkbox-indeterminate-value" => indeterminate,
66
+ "data-shadcn--checkbox-disabled-value" => disabled,
67
+ "data-shadcn--checkbox-input-id-value" => input_id,
68
+ "data-action" => "click->shadcn--checkbox#toggle keydown->shadcn--checkbox#keydown"
69
+ }.merge(defaults))
70
+ end
71
+
72
+ def call
73
+ safe_join([ render_element(body: indicator), hidden_input ].compact)
74
+ end
75
+
76
+ private
77
+
78
+ # Radix mounts the indicator only while checked. It is rendered here
79
+ # regardless — hidden when unchecked, so the markup is correct before
80
+ # JavaScript runs — and the controller detaches it on connect.
81
+ def indicator
82
+ tag.span(
83
+ render(Icon::Component.new("check", class: "size-3.5")),
84
+ "data-slot": "checkbox-indicator",
85
+ "data-state": state,
86
+ "data-shadcn--checkbox-target": "indicator",
87
+ hidden: (true if state == "unchecked"),
88
+ class: INDICATOR_CLASSES
89
+ )
90
+ end
91
+
92
+ def hidden_input
93
+ return unless name
94
+
95
+ tag.input(
96
+ type: "checkbox",
97
+ id: input_id,
98
+ name: name,
99
+ value: value,
100
+ checked: checked,
101
+ disabled: (true if disabled),
102
+ "aria-hidden": "true",
103
+ tabindex: "-1",
104
+ style: HIDDEN_INPUT_STYLE
105
+ )
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Checkbox
5
+ class Preview < ApplicationViewComponentPreview
6
+ def default
7
+ render_with_template
8
+ end
9
+
10
+ # Upstream's "Checked State" and "Invalid State", with indeterminate beside them.
11
+ def states
12
+ render_with_template
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ <div class="flex flex-col gap-4">
2
+ <div class="flex items-center gap-2">
3
+ <%= render(Shadcn::Checkbox::Component.new(id: "cb1", name: "terms")) %>
4
+ <%= render(Shadcn::Label::Component.new(for: "cb1")) { "Accept terms and conditions" } %>
5
+ </div>
6
+ <div class="flex items-center gap-2">
7
+ <%= render(Shadcn::Checkbox::Component.new(id: "cb2", checked: true)) %>
8
+ <%= render(Shadcn::Label::Component.new(for: "cb2")) { "Checked by default" } %>
9
+ </div>
10
+ <div class="flex items-center gap-2">
11
+ <%= render(Shadcn::Checkbox::Component.new(id: "cb3", disabled: true)) %>
12
+ <%= render(Shadcn::Label::Component.new(for: "cb3")) { "Disabled" } %>
13
+ </div>
14
+ </div>
@@ -0,0 +1,23 @@
1
+ <%# Upstream's "Checked State" and "Invalid State". Indeterminate is the one
2
+ worth seeing beside the other two: it is neither checked nor unchecked, and
3
+ a parent box summarising a part-ticked list is the whole reason it exists. %>
4
+ <div class="flex flex-col gap-4">
5
+ <div class="flex items-center gap-2">
6
+ <%= render(Shadcn::Checkbox::Component.new(id: "cbs1", indeterminate: true)) %>
7
+ <%= render(Shadcn::Label::Component.new(for: "cbs1")) { "Some of the below" } %>
8
+ </div>
9
+ <div class="ml-6 flex flex-col gap-2">
10
+ <div class="flex items-center gap-2">
11
+ <%= render(Shadcn::Checkbox::Component.new(id: "cbs2", checked: true)) %>
12
+ <%= render(Shadcn::Label::Component.new(for: "cbs2")) { "Ticked" } %>
13
+ </div>
14
+ <div class="flex items-center gap-2">
15
+ <%= render(Shadcn::Checkbox::Component.new(id: "cbs3")) %>
16
+ <%= render(Shadcn::Label::Component.new(for: "cbs3")) { "Not ticked" } %>
17
+ </div>
18
+ </div>
19
+ <div class="flex items-center gap-2">
20
+ <%= render(Shadcn::Checkbox::Component.new(id: "cbs4", "aria-invalid": "true")) %>
21
+ <%= render(Shadcn::Label::Component.new(for: "cbs4")) { "Has to be accepted" } %>
22
+ </div>
23
+ </div>
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Collapsible
5
+ # Port of registry/new-york-v4/ui/collapsible.tsx
6
+ class Component < ApplicationViewComponent
7
+ renders_one :trigger, "Shadcn::Collapsible::Trigger::Component"
8
+ renders_one :panel, "Shadcn::Collapsible::Content::Component"
9
+
10
+ slot_name :collapsible
11
+
12
+ attr_reader :open, :disabled
13
+
14
+ def initialize(open: false, disabled: false, **attributes)
15
+ @open = open
16
+ @disabled = disabled
17
+ super(**attributes)
18
+ end
19
+
20
+ def element_attributes(**defaults)
21
+ super(**{
22
+ "data-state" => open ? "open" : "closed",
23
+ "data-disabled" => (true if disabled),
24
+ "data-controller" => "shadcn--collapsible",
25
+ "data-shadcn--collapsible-open-value" => open,
26
+ "data-shadcn--collapsible-disabled-value" => disabled
27
+ }.merge(defaults))
28
+ end
29
+
30
+ def call
31
+ render_element(body: safe_join([ trigger, panel, content ].compact))
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Collapsible
5
+ module Content
6
+ # CollapsibleContent
7
+ class Component < ApplicationViewComponent
8
+ slot_name :"collapsible-content"
9
+
10
+ def element_attributes(**defaults)
11
+ super(**{
12
+ "data-state" => "closed",
13
+ hidden: true,
14
+ "data-shadcn--collapsible-target" => "content"
15
+ }.merge(defaults))
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Collapsible
5
+ class Preview < ApplicationViewComponentPreview
6
+ def default
7
+ render_with_template
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ <%= render(Shadcn::Collapsible::Component.new(class: "flex w-[420px] flex-col gap-2")) do |c| %>
2
+ <% c.with_trigger(class: "flex items-center justify-between rounded-md border px-4 py-2 text-sm font-medium") do %>
3
+ @peduarte starred 3 repositories
4
+ <% end %>
5
+ <% c.with_panel(class: "flex flex-col gap-2") do %>
6
+ <div class="rounded-md border px-4 py-2 font-mono text-sm">@radix-ui/colors</div>
7
+ <div class="rounded-md border px-4 py-2 font-mono text-sm">@stitches/react</div>
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Collapsible
5
+ module Trigger
6
+ # CollapsibleTrigger
7
+ class Component < ApplicationViewComponent
8
+ default_tag :button
9
+ slot_name :"collapsible-trigger"
10
+
11
+ def element_attributes(**defaults)
12
+ super(**{
13
+ type: "button",
14
+ "aria-expanded" => "false",
15
+ "data-state" => "closed",
16
+ "data-shadcn--collapsible-target" => "trigger",
17
+ "data-action" => "shadcn--collapsible#toggle"
18
+ }.merge(defaults))
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Combobox
5
+ module Chip
6
+ # One chosen value, with the X that takes it back off. `show_remove:` is
7
+ # upstream's `showRemove`, on by default there too.
8
+ class Component < ApplicationViewComponent
9
+ REMOVE_CLASSES = "-ml-1 opacity-50 hover:opacity-100"
10
+
11
+ default_tag :span
12
+ slot_name :"combobox-chip"
13
+
14
+ style do
15
+ base {
16
+ "flex h-[calc(--spacing(5.5))] w-fit items-center justify-center gap-1 rounded-sm bg-muted " \
17
+ "px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none " \
18
+ "has-disabled:cursor-not-allowed has-disabled:opacity-50 " \
19
+ "has-data-[slot=combobox-chip-remove]:pr-0"
20
+ }
21
+ end
22
+
23
+ attr_reader :value, :show_remove
24
+
25
+ def initialize(value: nil, show_remove: true, **attributes)
26
+ @value = value
27
+ @show_remove = show_remove
28
+ super(**attributes)
29
+ end
30
+
31
+ def element_attributes(**defaults)
32
+ super(**{
33
+ "data-value" => value,
34
+ "data-shadcn--combobox-target" => "chip"
35
+ }.compact.merge(defaults))
36
+ end
37
+
38
+ def call
39
+ render_element(body: safe_join([ content, remove ].compact))
40
+ end
41
+
42
+ private
43
+
44
+ def remove
45
+ return unless show_remove
46
+
47
+ render(Shadcn::Button::Component.new(
48
+ variant: :ghost,
49
+ size: :"icon-xs",
50
+ class: REMOVE_CLASSES,
51
+ "data-slot": "combobox-chip-remove",
52
+ "data-value": value,
53
+ "data-action": "click->shadcn--combobox#remove",
54
+ "aria-label": shadcn_t("combobox.remove")
55
+ )) { render(Icon::Component.new("x", class: "pointer-events-none")) }
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Combobox
5
+ module ChipInput
6
+ # The field that sits *among* the chips rather than inside an InputGroup:
7
+ # it takes whatever room is left on the last row.
8
+ class Component < Shadcn::Combobox::Input::Component
9
+ slot_name :"combobox-chip-input"
10
+
11
+ style do
12
+ base { "min-w-16 flex-1 outline-none" }
13
+ end
14
+
15
+ # This field has to carry its own name, and that is **ours** rather than
16
+ # upstream's — the same correction Select, Checkbox, Switch and the
17
+ # Combobox trigger each needed here.
18
+ #
19
+ # It is not theoretical. The only name this input had was its
20
+ # `placeholder`, and in multiple mode the controller blanks that once
21
+ # there are chips — which upstream's own example also does. The field
22
+ # was then a `role="combobox"` with no name at all, and axe failed it as
23
+ # `label`, critical. Caught by the accessibility spec on the run *after*
24
+ # the placeholder was wired up; the run before it could not see the
25
+ # interaction, because nothing blanked the placeholder yet.
26
+ #
27
+ # The caller's placeholder is used when there is one, because "Add a
28
+ # language…" names the field better than anything this gem could
29
+ # generate. Read at render time and never touched again, so the name
30
+ # stays put while the placeholder comes and goes.
31
+ def element_attributes(**defaults)
32
+ super(**{ "aria-label" => placeholder.presence || shadcn_t("combobox.add") }.merge(defaults))
33
+ end
34
+
35
+ # No InputGroup and no addons: the chips box is the frame, and a chevron
36
+ # would have nowhere to sit.
37
+ def call
38
+ render_element
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Combobox
5
+ module Chips
6
+ # The box that holds the chosen values as removable tokens, with the
7
+ # field beside them — upstream's multiple-selection shape.
8
+ #
9
+ # It is the field's own frame here rather than an InputGroup: upstream's
10
+ # classes draw the border, the ring and the invalid states themselves,
11
+ # because the box grows with its chips where an InputGroup does not.
12
+ class Component < ApplicationViewComponent
13
+ default_tag :div
14
+ slot_name :"combobox-chips"
15
+
16
+ style do
17
+ base {
18
+ "flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-transparent " \
19
+ "bg-clip-padding px-2.5 py-1.5 text-sm shadow-xs transition-[color,box-shadow] " \
20
+ "focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50 " \
21
+ "has-aria-invalid:border-destructive has-aria-invalid:ring-[3px] " \
22
+ "has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1.5 " \
23
+ "dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 " \
24
+ "dark:has-aria-invalid:ring-destructive/40"
25
+ }
26
+ end
27
+
28
+ def element_attributes(**defaults)
29
+ super(**{ "data-shadcn--combobox-target" => "chips" }.merge(defaults))
30
+ end
31
+
32
+ def call
33
+ render_element(body: safe_join([ content, template ]))
34
+ end
35
+
36
+ private
37
+
38
+ # One blank chip in a `<template>`, which the controller clones when a
39
+ # value is taken.
40
+ #
41
+ # The alternative was building the chip's markup in JavaScript, and that
42
+ # would put this library's class strings in two places — a `.js` file
43
+ # Tailwind does scan but `parity_spec` does not read, so the copy would
44
+ # drift from the component silently and upstream would never be checked
45
+ # against it. Cloning keeps one source: the Chip component.
46
+ def template
47
+ tag.template("data-shadcn--combobox-target": "chipTemplate") do
48
+ render(Shadcn::Combobox::Chip::Component.new)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ module Combobox
5
+ module Clear
6
+ # The X that empties the field. Upstream renders it through
7
+ # `InputGroupButton` too, and hides the chevron whenever it is present —
8
+ # which is what the trigger's
9
+ # `group-has-data-[slot=combobox-clear]/input-group:hidden` does.
10
+ class Component < Shadcn::InputGroup::Button::Component
11
+ slot_name :"combobox-clear"
12
+
13
+ def initialize(**attributes)
14
+ super(variant: :ghost, size: :"icon-xs", **attributes)
15
+ end
16
+
17
+ def element_attributes(**defaults)
18
+ super(**{
19
+ "data-shadcn--combobox-target" => "clear",
20
+ "data-action" => "click->shadcn--combobox#clear",
21
+ tabindex: "-1",
22
+ "aria-label" => shadcn_t("combobox.clear")
23
+ }.merge(defaults))
24
+ end
25
+
26
+ def call
27
+ render_element(body: render(Icon::Component.new("x", class: "pointer-events-none")))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end